java對多個對象加鎖

java中存在對多個對象加鎖的情況,例如: 在銀行系統轉賬時,需要鎖定兩個賬戶,這個時候,順序使用兩個synchronized可能存在死鎖的情況,在網上搜索到下面的例子:

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,就必須等待前一次操作完成,可能產生性能問題。(這裏應該有更好的方法)
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章