JavaRush/Курсы/Java Multithreading/DeadLock, и его причины

DeadLock, и его причины

Открыта
DeadLock, и его причины - 1

— Привет, Амиго!

Сегодня я тебе расскажу, что такое дедлок (DeadLock) — взаимная блокировка.

— Так ты же уже что-то такое рассказывала.

— Ага, было дело. Но сегодня мы рассмотрим эту тему детальнее.

В самом простом случае в дедлоке участвуют две нити и два объекта-мютекса. Взаимная блокировка возникает, когда:

А) Каждой нити в процессе работы нужно захватить оба мютекса.

Б) Первая нить захватила первый мютекс и ждет освобождения второго.

В) Вторая нить захватила второй мютекс и ждет освобождения первого.

Примеры:

Пример
public class Student
{
 private ArrayList friends = new ArrayList();

 public synchronized ArrayList getFriends()
 {
  synchronized(friends)
  {
   return new ArrayList(friends);
  }
 }

 public synchronized int getFriendsCount()
 {
  return friends.size();
 }

 public int addFriend(Student student)
 {
  synchronized(friends)
  {
   friends.add(student)
   return getFriendsCount();
  }
 }
}

Допустим, первая нить вызвала метод getFriends, тогда она сначала захватит мютекс объекта this, а затем мютекс объекта friends.

Вторая нить при этом вызвала метод addFriend, она сначала захватывает мютекс объекта friends, а затем мютекс объекта this (при вызове getFriendsCount).

Сначала все будет хорошо, но как гласит Закон Мерфи — если неприятность может случиться, она случается. Обязательно возникнет ситуация, когда первая нить успеет захватить только один мютекс, а вторая нить в это время захватит второй. Они так и будут висеть вечно в ожидании, что кто-то из них первым освободит мютекс.

Еще один простой пример, нашла в книге:

Пример
class KnightUtil
{
 public static void kill(Knight knight1, Knight knight2)
 {
  synchronized(knight1)
  {
   synchronized(knight2)
   {
    knight2.live = 0;
    knight1.experience +=100;
   }
  }
 }
}

Есть игра, где два рыцаря сражаются друг с другом. Один рыцарь убивает другого. Это поведение отражено в методе kill. Туда передаются два объекта-рыцаря.

Сначала мы защищаем оба объекта, чтобы никто больше не мог их изменить.

Второй рыцарь умирает (live=0)

Первый рыцарь получает +100 опыта.

Все вроде бы отлично, но иногда может возникнуть ситуация, когда второй рыцарь в это время атакует первого. Для него тоже вызывается этот метод, но рыцари передаются в другом порядке.

— Т.е. нам даже не нужно несколько методов для получения дедлока?

— Ага. Иногда бывает достаточно одного простого метода, в котором уже могут происходить процессы, приводящие к зависанию нитей и всей программы.

— Да, оказывается, это явление встречается чаще, чем я думал. Спасибо, Элли.

Комментарии (69)
  • популярные
  • новые
  • старые
Для того, чтобы оставить комментарий Вы должны авторизоваться
rusvasimov Java Developer
26 июня 2025, 06:55
😬
arsvasimov Java Developer в Phractal Client
26 июня 2025, 06:54
Мда...
12 февраля 2024, 15:27
Пример попроще:
public void transferMoney(Account a, Account b) {
    synchronized(a) {
        synchronized(b) {
            // Перевод средств
        }
    }
}

transferMoney(john, sam);
transferMoney(sam, john);
Метод transferMoney вызывается двумя разными потоками. Первый поток захватывает мьютекс с именем john, в этот же момент другой поток захватывает мьютекс с именем sam. После оба переходят в блок захвата следующего мьютекса, но обнаруживают что для первого потока sam уже занят, а для другого john уже занят. Вот и сидят, ждут, кто освободит, чтобы продолжить работу.
Fl1s Backend Developer
11 августа 2023, 01:41
Это победа
FeliV
Уровень 51
Student
25 декабря 2023, 23:31
грац я тоже пытался получать эти ачивки, в итоге это привело к тому, что иногда я заходил на джаваращ чисто скопировать и вставить решение задачи, т.к. времени не было вообще, в итоге один раз все слетело и я вообще перестал гнаться
Fl1s Backend Developer
4 января 2024, 14:26
Блин, жиза...Вот только у меня не слетело
AliransaРаботает в стажировка
26 сентября 2024, 08:33
когда совсем нету времени, прохожу одну задачу из игр) там есть совсем простенькие) ну или откладываю решенную, но не проверенную, если понимаю, что сейчас больше не сделаю, а завтра времени не будет
Voffka
Уровень 49
4 января 2023, 21:15
пример с рыцарями не понятен, т.к. он не полный. Я так и не понял где там дедлок
Anonymous #3048388
Уровень 43
8 января 2023, 08:04
"иногда может возникнуть ситуация, когда второй рыцарь в это время атакует первого. Для него тоже вызывается этот метод, но рыцари передаются в другом порядке." Один метод используется в разных нитях. Первая нить сначала блокирует knight1 (например, нападающий рыцарь). Вторая нить сначала блокирует knight1 (соответственно, защищающийся рыцарь)
Тимофей ФилипповJava Developer в Снэп-Айти
11 февраля 2023, 18:10
2 разных объекта. Каждый из них применяет метод. Метод в классе один, но тут 2 метода от разных объектов. Методы (по сути выполнения это один метод) блокируют друг друга.
Anonymous #311541 Java Developer
20 апреля 2024, 15:54
Допустим есть 2 рыцаря - Вася и Олег, это 2 объекта. Началась битва. Мочилово каждого рыцаря контрлирует отдельный поток. Для Васи это поток1 а для Олега поток 2. Поток 1 берет метод KnightUtil.kill и пытается им убить соперника Васи - сначала он лочит Васю и уже собирается залочить Олега, но не успевает (не факт что это произойдет сразу, но если делать много раз то такая ситуация может случиться) , поток2 (который за Олега и хочет замочить Васю) тоже зашел в этот метод, как раз после того как это сделал поток1, и залочил Васю. И получается что поток1 ждет пока освободится Вася (knight2) а поток2 ждет пока освободится Олег.
Knight vasia = new Knight("Vasia")
 Knight oleg = new Knight("Oleg");
// при многократном повторе здесь может получится дедлок
new Thread(() -> KnightUtil.kill(vasia, oleg)).start();
new Thread(() -> KnightUtil.kill(oleg, vasia)).start();
Михаил
Уровень 32
22 декабря 2022, 09:55
Пришла в голову шальная мысль. А почему бы не придумать отдельную хрень, которая все время проверяет на дэдлок и в случае превышения таймаута рандомно разблокирует одного из оленей? Ответ: а зачем плодить сущности сверх меры?
Anonymous #3048388
Уровень 43
8 января 2023, 08:06
Логика обработки может быть нарушена. Или данные будут не соответствовать.
hidden #2513091
Уровень 44
19 декабря 2021, 11:42
Вафельница на перекрестке. DeadLock
Vit
Уровень 33
12 октября 2021, 18:52
"У каждого объекта в Java есть замок. У каждого замка только один ключ. Большую часть времени замок открыт и никому нет до него дела. Но если у объекта есть синхронизированные методы, поток может выполнять их, когда доступен ключ для данного объекта. Иначе говоря, пока другой поток не завладел единственным ключом." - с. 541, Изучаем Java. "Настоящая система по управлению транзакциями способна справиться с отдельными случаями взаимного блокирования. Она может распознать их, например, когда две транзакции выполняются слишком долго. Но в отличие от Java такие серверные приложения умеют делать "откат", когда состояние данных возвращается к моменту до выполнения транзакции (атомарность в действии). У Java нет механизмов для противодействия взаимному блокированию. JVM даже не будет знать, что это случилось. Будьте осторожны при проектировании, так как вся ответственность лежит на вас." - с. 546, Изучаем Java.
12 октября 2022, 12:31
тоже прочитал эту книгу. что касается Thread-ов, то там ото только про deadlock, synchronized и sleep написано и все. Здесь и то больше )) а в остальном книга хорошая
Игорь
Уровень 34
19 апреля 2021, 11:46
Дедлок это когда ты ищешь работу на позицию Джуна, но тебя не берут, потому что нет опыта работы на реальном проекте
Anonymous #2489173
Уровень 35
12 июня 2021, 09:11
не, это лайвлок, потому что жиза
Anonymous #2524703
Уровень 28
24 июля 2021, 18:55
Запусти свой проект, вот и опыт тебе будет. Или открой фирму на родственника, и трудоустройся в нее программистом. Вот еще опыт.
PaiMei in J#Grand Master в Eagles' Claw
9 сентября 2021, 21:31
Со школы слышал про такой лок, по опыту могу сказать - софт скилс решают) Обучить человека всегда можно, а вот если у него характер и эмоциональный интеллект как у бревна, то вот тут уже обучение на вряд ли поможет)
Andrey Karelin
Уровень 41
1 апреля 2022, 16:55
Этот дедлок легко решаем: делаем ЗП 100-200$ с испытательным сроком 1...3 месяца...и все понятно - человек плавно движется к Джуну или не подходит вовсе. Посадите, пусть ковыряется и растет "за еду". Но все хотят охулиард опыта, и практических знаний, как у мидла.
Vadym
Уровень 34
18 января 2024, 03:01
эти данные устарели... теперь хотят джуна на вакансию джина с з/п помошника уборщицы. еше и желаюших 50 человек
27 марта 2021, 11:58
прищемило причиндал в лифте дверью и при этом отключили свет, это пожалуй забавный дедлок.
GvardeeZZZ
Уровень 41
17 января 2022, 18:54
Страшно представить, что там за run {}!!!
Kurama
Уровень 50
12 ноября 2022, 20:02
Это ж не дэдлок