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,就必須等待前一次操作完成,可能產生性能問題。(這裏應該有更好的方法)