DeadLock

Модуль 2. Java Core
12 уровень , 0 лекция
Открыта

— Привет, Амиго! Вчера мы обсудили преимущества и удобства, которые несет с собой многонитиевость (multithreading). Теперь пора взглянуть и на минусы. А они, к сожалению, не маленькие.

Раньше мы смотрели на программу, как на набор объектов, которые вызывают методы друг друга. Теперь все стало немного сложнее. Программа – это скорее набор объектов, по которым лазает несколько «маленьких роботиков» – нитей – и выполняют команды, содержащиеся в методах.

Формально – второе не отменяет первое. Это все еще объекты, и они все еще вызывают методы друг у друга. Но нужно не забывать, что нитей – несколько, и каждая нить выполняет свою работу – свое задание.

Программа становится сложнее. Разные нити меняют состояние разных объектов в соответствии с задачей, которую каждая из них выполняет. И могут мешать друг другу.

Но самое страшное происходит глубоко внутри Java-машины. Как я уже рассказывала, видимая одновременность работы нитей достигается за счет того, что процессор постоянно переключается с одной нити на другую. Переключился на нить, поработал 10 миллисекунд, переключился на следующую нить, там поработал 10 миллисекунд и так далее. И тут возникает проблема: переключение может произойти в самый неподходящий момент. Пример:

Код первой нити Код второй нити
System.out.print ("Коле"); System.out.print (" "); System.out.print ("15"); System.out.print (" "); System.out.print ("лет");
System.out.println ();
System.out.print ("Лене"); System.out.print (" "); System.out.print ("21"); System.out.print (" "); System.out.print ("год");
System.out.println ();
Ожидаемый вывод на консоль
Коле 15 лет
Лене 21 год
Итоговый порядок Код первой нити Код второй нити
System.out.print ("Коле");
System.out.print ("Лене"); System.out.print (" ");
System.out.print (" "); System.out.print ("15");
System.out.print ("21"); System.out.print (" ");
System.out.print (" "); System.out.print ("лет"); System.out.println ();
System.out.print ("год"); System.out.println ();
System.out.print ("Коле");
//исполняется другая нить
//исполняется другая нить
System.out.print (" "); System.out.print ("15"); //исполняется другая нить
//исполняется другая нить
System.out.print (" "); System.out.print ("лет"); System.out.println ();
//исполняется другая нить
//исполняется другая нить
//исполняется другая нить
System.out.print ("Лене"); System.out.print (" ");
//исполняется другая нить
//исполняется другая нить
System.out.print ("21"); System.out.print (" ");
//исполняется другая нить
//исполняется другая нить
//исполняется другая нить
System.out.print ("год"); System.out.println ();
Реальный вывод на консоль
Коле
Лене
15
21
лет
год

Или вот еще пример:

Код Описание
class MyClass {
    private String name1 = "Оля";
    private String name2 = "Лена";
    public void swap() {
        String s = name1;
        name1 = name2;
        name2 = s;
    }
}
Метод swap меняет местами значения переменных name1 & name2.

Что же будет если его вызывать из двух нитей одновременно?

Итоговый порядок Код первой нити Код второй нити
String s1 = name1; //Оля
name1 = name2; //Лена
String s2 = name1; //Лена(!)
name1 = name2; //Лена
name2 = s1; //Оля
name2 = s2; //Лена
String s1 = name1; name1 = name2;
//исполняется другая нить
//исполняется другая нить
name2 = s1;
//исполняется другая нить
//исполняется другая нить
//исполняется другая нить
String s2 = name1; name1 = name2;
//исполняется другая нить
name2 = s2;
Итог
Обе переменных имеют значение «Лена».
Объект «Оля» был перезатерт и потерян.

— Кто бы мог подумать, что при элементарном присваивании возможны такие ошибки?

— Да, но для этой проблемы есть решение. Но об этом немного позже – у меня горло пересохло.

Комментарии (12)
ЧТОБЫ ПОСМОТРЕТЬ ВСЕ КОММЕНТАРИИ ИЛИ ОСТАВИТЬ КОММЕНТАРИЙ,
ПЕРЕЙДИТЕ В ПОЛНУЮ ВЕРСИЮ
I'm Siberian Уровень 109 Expert
14 сентября 2024
Программа должна выводить текст на экран. ок, сделали, запускаем - false ... секунд 5 тупим под звуки сверчков в голове. потом понимаем что false это текст же... жмак "проверить" профит
Тимур Уровень 109
11 сентября 2024
Всё понятно, но причём тут DeadLock?
I'm Siberian Уровень 109 Expert
14 сентября 2024
Дык у него же горло пересохло) — Да, но для этой проблемы есть решение. Но об этом немного позже – у меня горло пересохло.
Олег Уровень 79 Expert
6 июля 2023
смысл в этих 2 задачах??? Подскажите кто понял? Показать что многопоточность сеет хаос в решении без синхронизации?
Руслан Никитин Уровень 109
11 сентября 2024
если постараться и позапускать задачки через сайт, то можно в первой словить ArrayIndexOutOfBoundsException а во второй получить в конце false. Задачи показывают состояние гонки между потоками.
I'm Siberian Уровень 109 Expert
14 сентября 2024
запустил оверь 50 раз. всегда false )))
Руслан Никитин Уровень 109
14 сентября 2024
решал на работе через сайт и результат true почти всегда) поправил коммент) сорян)
Руслан Уровень 48
10 октября 2025
да именно что потоки которые работают с общими данными творят дич с этими данными без синхронизации а синхронизация в тоже время не ускоряет работу а возвращается в однопоток по сути но это плата за стабильность
Татьяна Уровень 48 Expert
4 июля 2023
Лучше решать сначала "Вместе быстрее? Ща проверим :)" и после неё уже "Заметки"...
Екатерина Уровень 70 Expert
8 сентября 2022
Смысл далек от h1 статьи.
JRU Mentor Уровень 108
27 декабря 2022
Есть немного)
Владимир Уровень 109 Expert
20 июня 2022
Заголовок статьи должен быть DataRace судя по всему описанному.