开发者

Java Threading Deadlock

开发者 https://www.devze.com 2023-02-22 19:06 出处:网络
I am reading Java Concurrency in Practice and got stuck on this program,where author say it won\'t cause the deadlock. But if I swap the method argume开发者_如何学Gonts then it will cause deadlock.

I am reading Java Concurrency in Practice and got stuck on this program,where author say it won't cause the deadlock. But if I swap the method argume开发者_如何学Gonts then it will cause deadlock.

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

Thread1. transfer(Obj1, Obj2) will get lock on fromAcct and will wait for toAcct lock

Thread2.transfer(Obj2, Obj1) will get lock on toAcct and will wait for fromAcct lock

So basically we ended-up in dead-lock.

My question is how come is the dead-lock is avoided in following code.

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 {
    }
}


Your example states that it is in fact correct.

Case 1: Thread1.transfer(Obj1, Obj2)

In this case, fromHash < toHash so the first lock is on the fromAcct param or Obj1 and the second is on the toAcct param or Obj2

Case 2: Thread1.transfer(Obj2, Obj1)

In this case, fromHash > toHash so the first lock is on the toAcct param or Obj1 and the second is on the fromAcct param or Obj2

Lock order is same, so no deadlock occurs.

0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号