DeadLock

Открыта

— Привет, Амиго! Вчера мы обсудили преимущества и удобства, которые несет с собой многонитиевость (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;
Итог
Обе переменных имеют значение «Лена».
Объект «Оля» был перезатерт и потерян.

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

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

Комментарии (13)
  • популярные
  • новые
  • старые
Для того, чтобы оставить комментарий Вы должны авторизоваться
Манэки-нэко
Уровень 72
16 января, 10:19
Причем тут DeadLock?
I'm Siberian Trust me, i'm an engineer Expert
14 сентября 2024, 07:29
Программа должна выводить текст на экран. ок, сделали, запускаем - false ... секунд 5 тупим под звуки сверчков в голове. потом понимаем что false это текст же... жмак "проверить" профит
Тимур
Уровень 109
11 сентября 2024, 13:52
Всё понятно, но причём тут DeadLock?
I'm Siberian Trust me, i'm an engineer Expert
14 сентября 2024, 07:24
Дык у него же горло пересохло) — Да, но для этой проблемы есть решение. Но об этом немного позже – у меня горло пересохло.
Олег
Уровень 79
Expert
6 июля 2023, 10:11
смысл в этих 2 задачах??? Подскажите кто понял? Показать что многопоточность сеет хаос в решении без синхронизации?
11 сентября 2024, 04:06
если постараться и позапускать задачки через сайт, то можно в первой словить ArrayIndexOutOfBoundsException а во второй получить в конце false. Задачи показывают состояние гонки между потоками.
I'm Siberian Trust me, i'm an engineer Expert
14 сентября 2024, 07:31
запустил оверь 50 раз. всегда false )))
14 сентября 2024, 10:07
решал на работе через сайт и результат true почти всегда) поправил коммент) сорян)
Руслан
Уровень 48
10 октября 2025, 05:14
да именно что потоки которые работают с общими данными творят дич с этими данными без синхронизации а синхронизация в тоже время не ускоряет работу а возвращается в однопоток по сути но это плата за стабильность
Татьяна
Уровень 48
Expert
4 июля 2023, 19:33
Лучше решать сначала "Вместе быстрее? Ща проверим :)" и после неё уже "Заметки"...
Екатерина
Уровень 70
Expert
8 сентября 2022, 16:47
Смысл далек от h1 статьи.
JRU Mentor
Уровень 108
27 декабря 2022, 14:35
Есть немного)
Владимир
Уровень 109
Expert
20 июня 2022, 11:02
Заголовок статьи должен быть DataRace судя по всему описанному.