首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > 开发语言 > 编程 >

java锁 两个顺序的同步引起的有关问题

2012-12-26 
java锁 两个顺序的同步引起的问题java中存在对多个对象加锁的情况,例如: 在银行系统转账时,需要锁定两个账

java锁 两个顺序的同步引起的问题
java中存在对多个对象加锁的情况,例如: 在银行系统转账时,需要锁定两个账户,这个时候,顺序使用两个synchronized可能存在死锁的情况,在网上搜索到下面的例子:


Java代码 
1.public class Bank {  
2.    final static Object obj_lock = new Object();  
3. 
4.    // Deadlock crisis  
5.    public void transferMoney(Account from, Account to, int number) {  
6.        synchronized (from) {  
7.            synchronized (to) {  
8.                from.debit();  
9.                to.credit();  
10.            }  
11.        }  
12.    }  
13. 
14.    // Thread safe  
15.    public void transferMoney2(final Account from, final Account to, int number) {  
16.        class Help {  
17.            void transferMoney2() {  
18.                from.debit();  
19.                to.credit();  
20.            }  
21.        }  
22. 
23.        int fromHash = from.hashCode();  
24.        int toHash = to.hashCode();  
25.        if (fromHash < toHash) {  
26.            synchronized (from) {  
27.                synchronized (to) {  
28.                    new Help().transferMoney2();  
29.                }  
30.            }  
31.        } else if (toHash < fromHash) {  
32.            synchronized (to) {  
33.                synchronized (from) {  
34.                    new Help().transferMoney2();  
35.                }  
36.            }  
37.        } else {  
38.            synchronized (obj_lock) {  
39.                synchronized (to) {  
40.                    synchronized (from) {  
41.                        new Help().transferMoney2();  
42.                    }  
43.                }  
44.            }  
45.        }  
46.    }  
47.} 
public class Bank {
final static Object obj_lock = new Object();

// Deadlock crisis
public void transferMoney(Account from, Account to, int number) {
synchronized (from) {
synchronized (to) {
from.debit();
to.credit();
}
}
}

// Thread safe
public void transferMoney2(final Account from, final Account to, int number) {
class Help {
void transferMoney2() {
from.debit();
to.credit();
}
}

int fromHash = from.hashCode();
int toHash = to.hashCode();
if (fromHash < toHash) {
synchronized (from) {
synchronized (to) {
new Help().transferMoney2();
}
}
} else if (toHash < fromHash) {
synchronized (to) {
synchronized (from) {
new Help().transferMoney2();
}
}
} else {
synchronized (obj_lock) {
synchronized (to) {
synchronized (from) {
new Help().transferMoney2();
}
}
}
}
}
}

若操作账户A,B:
1 A的hashCode小于B, 先锁A再锁B
2 B的hashCode小于A, 先锁B再锁A
3 产生的hashCode相等,先锁住一个全局静态变量,在锁A,B

这样就避免了两个线程分别操作账户A,B和B,A而产生死锁的情况。

注意点:
  1 需要为Account对象写一个好的hashCode算法,使得不同账户间产生的hashCode尽量不同。
  2 如果某次产生hashCode相同锁住obj_lock,那么如果有新的操作再次产生相同hashCode,就必须等待前一次操作完成,可能产生性能问题。(这里应该有更好的方法)

热点排行