Java线程死锁

时间:2011-04-06 18:24:16

标签: multithreading deadlock

我正在阅读Java Concurrency in Practice并且坚持这个程序,作者说它不会导致死锁。但是,如果我交换方法参数,那么它将导致死锁。

Obj1 = hash-code =1
Obj2 = hash-code =2

Thread1. transfer(Obj1, Obj2)将从来自theAcct锁定并等待toAcct lock

Thread2.transfer(Obj2, Obj1)将锁定toAcct并等待fromAcct lock

所以基本上我们最终陷入了死锁。

我的问题是如何在以下代码中避免死锁。

public class InduceLockOrder {
    private static final Object tieLock = new Object();

    public void transferMoney(final Account fromAcct,
                              final Account toAcct,
                              final DollarAmount amount)
            throws InsufficientFundsException {
        class Helper {
            public void transfer() throws InsufficientFundsException {
                if (fromAcct.getBalance().compareTo(amount) < 0)
                    throw new InsufficientFundsException();
                else {
                    fromAcct.debit(amount);
                    toAcct.credit(amount);
                }
            }
        }
        int fromHash = System.identityHashCode(fromAcct);
        int toHash = System.identityHashCode(toAcct);

        if (fromHash < toHash) {
            synchronized (fromAcct) {
                synchronized (toAcct) {
                    new Helper().transfer();
                }
            }
        } else if (fromHash > toHash) {
            synchronized (toAcct) {
                synchronized (fromAcct) {
                    new Helper().transfer();
                }
            }
        } else {
            synchronized (tieLock) {
                synchronized (fromAcct) {
                    synchronized (toAcct) {
                        new Helper().transfer();
                    }
                }
            }
        }
    }

    interface DollarAmount extends Comparable<DollarAmount> {
    }

    interface Account {
        void debit(DollarAmount d);

        void credit(DollarAmount d);

        DollarAmount getBalance();

        int getAcctNo();
    }

    class InsufficientFundsException extends Exception {
    }
}

1 个答案:

答案 0 :(得分:0)

您的示例表明它实际上是正确的。

案例1:Thread1.transfer(Obj1, Obj2)

在这种情况下,fromHash < toHash因此第一个锁定位于fromAcct参数或Obj1,第二个锁定位于toAcct参数或Obj2 < / p>

案例2:Thread1.transfer(Obj2, Obj1)

在这种情况下,fromHash > toHash因此第一个锁定位于toAcct参数或Obj1,第二个锁定位于fromAcct参数或Obj2 < / p>

锁定顺序相同,因此不会发生死锁。