public void transferMoney(Account from, Account to, int amount) {
synchronized(from) {
synchronized(to) {
if (from.getBalance() < amount) throw new InsufficientFundsException();
from.debit(amount);
to.credit(amount);
}
}
}
// 強制規定:永遠先鎖 id 較小的帳戶
public void transferMoney(Account from, Account to, int amount) {
Account first = from.getId() < to.getId() ? from : to;
Account second = from.getId() < to.getId() ? to : from;
synchronized(first) {
synchronized(second) {
// 業務邏輯
}
}
}
缺點:需業務對象有唯一可比較 ID,侵入業務模型
public class DeadLockFreeTransfer {
private static final Object TIE_LOCK = new Object(); // 加時賽鎖
public void transferMoney(Account from, Account to, int amount)
throws InsufficientFundsException {
int fromHash = System.identityHashCode(from);
int toHash = System.identityHashCode(to);
if (fromHash < toHash) {
synchronized(from) { synchronized(to) { doTransfer(from, to, amount); } }
} else if (toHash < fromHash) {
synchronized(to) { synchronized(from) { doTransfer(from, to, amount); } }
} else {
// 雜湊碼碰撞極低概率:加時賽鎖
synchronized(TIE_LOCK) {
synchronized(from) { synchronized(to) { doTransfer(from, to, amount); } }
}
}
}
private void doTransfer(Account from, Account to, int amount)
throws InsufficientFundsException {
if (from.getBalance() < amount) throw new InsufficientFundsException();
from.debit(amount);
to.credit(amount);
}
}
class Helper {
public void transfer() { ... } // 捕獲外部 final 參數
}
// 使用:new Helper().transfer();
public static void main(String[] args) {
Account a1 = new Account(1000);
Account a2 = new Account(1000);
ExecutorService pool = Executors.newFixedThreadPool(10);
// 5 個執行緒 A->B
for (int i = 0; i < 5; i++) {
pool.execute(() -> transferMoney(a1, a2, 100));
}
// 5 個執行緒 B->A
for (int i = 0; i < 5; i++) {
pool.execute(() -> transferMoney(a2, a1, 100));
}
pool.shutdown();
// 無死鎖,正常完成
}
| 策略 | 原理 | 適用場景 |
|---|---|---|
| 固定加鎖順序 | 業務層面規定順序 | 有自然排序鍵的對象 |
| 雜湊碼排序 | 對象身份雜湊碼排序 | 通用、無侵入 |
| tryLock + 超時 | Lock.tryLock(timeout) | 可中斷、需超時控制 |
| 開放調用 | 持有鎖時不調用外部方法 | 避免嵌套鎖 |
| 鎖分級 | 分層加鎖,高層先獲取 | 複雜系統 |
**雜湊碼排序 + 加時賽鎖** 是解決無自然排序對象死鎖的通用最佳方案:
此模式廣泛應用於資料庫連線池、緩存框架等核心組件中。