Страницы

Поиск по вопросам

понедельник, 24 февраля 2020 г.

Не понятна логика возникновения DeadLock

#java #synchronized


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);
            }
        }
    }
}


Описание: Если со счета A на счет B перевести x денег, а со счета B на счет A – y,
то при неудачном стечении обстоятельств, транзакция 1 займет монитор счета A, транзакция
2 займет монитор счета B. Результат – взаимная блокировка.

Я никак не могу понять: Как же второй трэд доберётся до второго synchronized, если
первый synchronized уже был заблокирован первым трэдом?
Пересмотрел уже кучу лекций и перечитал про synchronized.
    


Ответы

Ответ 1



Он не будет заблокирован. synchronized воспользуется intrinsic lock того объекта, который будет указан в самом synchronized, поэтому два потока могут войти во внешний synchronized при том условии, что они используют два разных объекта: де-факто, synchronized(lockObject) - это гарантия использования объекта только одним потоком, но не гарантия исполнения кода максимум одним потоком в любой момент времени. Для достижения дедлока в этом случае достаточно, чтобы ни один из потоков не смог войти во внутренний synchronized - и это условие выполняется, если используются те же два аккаунта, но в противоположных потоках: Thread 1 | Thread 2 -------------------|------------------- обычное состояние | обычное состояние взял лок объекта А | взял лок объекта Б ждет лок объекта Б | ждет лок объекта А В этом случае прогресс невозможен, потому что для освобождения ресурса требуется прогресс любого из потоков, а это возможно только в случае освобождения ресурса.

Комментариев нет:

Отправить комментарий