public void transferMoney(Account fromAccount, Account toAccount, Amount amount) throws InsufficientFundsException { synchronized (fromAccount) { synchronized (toAccount) { if (fromAccount.getBalance().compareTo(amount) < 0) throw new InsufficientFundsException(); else { fromAccount.debit(amount); toAccount.credit(amount); } } } } 

Description: If from account A to account B to transfer x money, and from account B to account A - y, then if the circumstances fail, transaction 1 will take account monitor A, transaction 2 will take account monitor B. Result is a deadlock.

I just can not understand: How does the second trad get to the second synchronized, if the first synchronized has already been blocked by the first trad? I reviewed a bunch of lectures and reread synchronized.

  • one
    If you are given an exhaustive answer, mark it as correct (a daw opposite the selected answer). - Nicolas Chabanovsky

1 answer 1

It will not be blocked. synchronized will use the intrinsic lock of the object that will be specified in the synchronized itself, so two threads can enter the external synchronized provided that they use two different objects: de facto, synchronized(lockObject) is a guarantee of using the object only by one thread, but not a guarantee of the execution of a code with a maximum of one thread at any time To achieve deadlock in this case, it is enough that none of the threads could enter the internal synchronized - and this condition is met if the same two accounts are used, but in opposite threads:

 Thread 1 | Thread 2 -------------------|------------------- обычное состояние | обычное состояние взял лок объекта А | взял лок объекта Б ждет лок объекта Б | ждет лок объекта А 

In this case, progress is impossible, because the release of a resource requires the progress of any of the streams, and this is possible only if the resource is released.