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

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

Java Multithreading
7 уровень , 3 лекция
Открыта
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 Уровень 51
26 июня 2025
😬
arsvasimov Уровень 51
26 июня 2025
Мда...
12 февраля 2024
Пример попроще:

public void transferMoney(Account a, Account b) {
    synchronized(a) {
        synchronized(b) {
            // Перевод средств
        }
    }
}

transferMoney(john, sam); 
transferMoney(sam, john); 
Метод transferMoney вызывается двумя разными потоками. Первый поток захватывает мьютекс с именем john, в этот же момент другой поток захватывает мьютекс с именем sam. После оба переходят в блок захвата следующего мьютекса, но обнаруживают что для первого потока sam уже занят, а для другого john уже занят. Вот и сидят, ждут, кто освободит, чтобы продолжить работу.
Fl1s Уровень 51
11 августа 2023
Это победа
FeliV Уровень 51 Student
25 декабря 2023
грац я тоже пытался получать эти ачивки, в итоге это привело к тому, что иногда я заходил на джаваращ чисто скопировать и вставить решение задачи, т.к. времени не было вообще, в итоге один раз все слетело и я вообще перестал гнаться
Fl1s Уровень 51
4 января 2024
Блин, жиза...Вот только у меня не слетело
Aliransa Уровень 41
26 сентября 2024
когда совсем нету времени, прохожу одну задачу из игр) там есть совсем простенькие) ну или откладываю решенную, но не проверенную, если понимаю, что сейчас больше не сделаю, а завтра времени не будет
Voffka Уровень 49
4 января 2023
пример с рыцарями не понятен, т.к. он не полный. Я так и не понял где там дедлок
Anonymous #3048388 Уровень 43
8 января 2023
"иногда может возникнуть ситуация, когда второй рыцарь в это время атакует первого. Для него тоже вызывается этот метод, но рыцари передаются в другом порядке." Один метод используется в разных нитях. Первая нить сначала блокирует knight1 (например, нападающий рыцарь). Вторая нить сначала блокирует knight1 (соответственно, защищающийся рыцарь)
11 февраля 2023
2 разных объекта. Каждый из них применяет метод. Метод в классе один, но тут 2 метода от разных объектов. Методы (по сути выполнения это один метод) блокируют друг друга.
Anonymous #311541 Уровень 1
20 апреля 2024
Допустим есть 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
Пришла в голову шальная мысль. А почему бы не придумать отдельную хрень, которая все время проверяет на дэдлок и в случае превышения таймаута рандомно разблокирует одного из оленей? Ответ: а зачем плодить сущности сверх меры?
Anonymous #3048388 Уровень 43
8 января 2023
Логика обработки может быть нарушена. Или данные будут не соответствовать.
Yarik Уровень 44
19 декабря 2021
Вафельница на перекрестке. DeadLock
Vit Уровень 33
12 октября 2021
"У каждого объекта в Java есть замок. У каждого замка только один ключ. Большую часть времени замок открыт и никому нет до него дела. Но если у объекта есть синхронизированные методы, поток может выполнять их, когда доступен ключ для данного объекта. Иначе говоря, пока другой поток не завладел единственным ключом." - с. 541, Изучаем Java. "Настоящая система по управлению транзакциями способна справиться с отдельными случаями взаимного блокирования. Она может распознать их, например, когда две транзакции выполняются слишком долго. Но в отличие от Java такие серверные приложения умеют делать "откат", когда состояние данных возвращается к моменту до выполнения транзакции (атомарность в действии). У Java нет механизмов для противодействия взаимному блокированию. JVM даже не будет знать, что это случилось. Будьте осторожны при проектировании, так как вся ответственность лежит на вас." - с. 546, Изучаем Java.
12 октября 2022
тоже прочитал эту книгу. что касается Thread-ов, то там ото только про deadlock, synchronized и sleep написано и все. Здесь и то больше )) а в остальном книга хорошая
Игорь Уровень 34
19 апреля 2021
Дедлок это когда ты ищешь работу на позицию Джуна, но тебя не берут, потому что нет опыта работы на реальном проекте
Anonymous #2489173 Уровень 35
12 июня 2021
не, это лайвлок, потому что жиза
Anonymous #2524703 Уровень 28
24 июля 2021
Запусти свой проект, вот и опыт тебе будет. Или открой фирму на родственника, и трудоустройся в нее программистом. Вот еще опыт.
PaiMei in J# Уровень 35
9 сентября 2021
Со школы слышал про такой лок, по опыту могу сказать - софт скилс решают) Обучить человека всегда можно, а вот если у него характер и эмоциональный интеллект как у бревна, то вот тут уже обучение на вряд ли поможет)
Andrey Karelin Уровень 41
1 апреля 2022
Этот дедлок легко решаем: делаем ЗП 100-200$ с испытательным сроком 1...3 месяца...и все понятно - человек плавно движется к Джуну или не подходит вовсе. Посадите, пусть ковыряется и растет "за еду". Но все хотят охулиард опыта, и практических знаний, как у мидла.
Vadym Уровень 34
18 января 2024
эти данные устарели... теперь хотят джуна на вакансию джина с з/п помошника уборщицы. еше и желаюших 50 человек
27 марта 2021
прищемило причиндал в лифте дверью и при этом отключили свет, это пожалуй забавный дедлок.
GvardeeZZZ Уровень 41
17 января 2022
Страшно представить, что там за run {}!!!
Kurama Уровень 50
12 ноября 2022
Это ж не дэдлок