synchronized

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

— Привет, Амиго! У нас есть панацея – лекарство от всех болезней. Как мы уже успели убедиться – неконтролируемое переключение нитей – это проблема.

— А почему бы нитям самим не решать, когда переключиться на следующую? Сделала все важные дела и «маякует», я – все!

— Разрешать нитям самим управлять своим переключением – еще большая проблема. Вдруг какой-то код не очень красиво написан, и нить никогда сама не отдаст свое «процессорное время». Давным-давно так и было – и это был тихий ужас.

— Ладно. И какое же решение есть?

 Блокировка нитей. И вот как это работает.

Было выяснено, что нити мешают друг другу, когда пытаются сообща работать с общими объектами и/или ресурсами. Как в примере с выводом на консоль: консоль одна, а выводят на нее все нити. Непорядок.

Поэтому был придуман специальный объект – мютекс. Это как табличка на двери туалета «свободно» «занято». Он имеет два состояния – объект свободен и объект занят, или их еще называют заблокирован и разблокирован.

Когда какой-то нити нужен общий для всех нитей объект, она проверяет мютекс, связанный с этим объектом. Если мютекс свободен, то нить блокирует его (помечает как занятый) и начинает использование общего ресурса. После того как она сделала свои дела, мютекс разблокируется (помечается как свободен).

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

— А как работать с этим мютексом. Надо создавать специальные объекты?

— Все намного проще. Разработчики Java встроили этот мютекс в класс Object. Тебе даже создавать его не придется. Он есть у каждого объекта. Вот как это все работает:

Код Описание
class MyClass
{
private String name1 = "Оля";
private String name2 = "Лена";

public void swap()
{
synchronized (this)
{
String s = name1;
name1 = name2;
name2 = s;
}
}
}
Метод swap меняет местами значения переменных name1 & name2.

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

Итоговый порядок Код первой нити Код второй нити
String s1 = name1; //Оля
name1 = name2; //Лена
name2 = s1; //Оля

String s2 = name1; //Лена
name1 = name2; //Оля
name2 = s2; //Лена
String s1 = name1; name1 = name2;
name2 = s1;
//исполняется другая нить
//исполняется другая нить
//исполняется другая нить
//нить ждет, пока освободится мютекс
//нить ждет, пока освободится мютекс
//нить ждет, пока освободится мютекс
String s2 = name1; name1 = name2;
name2 = s2;
Итог
Значения переменных были дважды обменяны местами и вернулись на первоначальное место.

Обрати внимание на ключевое слово synchronized.

— Да, а что оно значит?

— Когда одна нить заходит внутрь блока кода, помеченного словом synchronized, то Java-машина тут же блокирует мютекс у объекта, который указан в круглых скобках после слова synchronized. Больше ни одна нить не сможет зайти в этот блок, пока наша нить его не покинет. Как только наша нить выйдет из блока, помеченного synchronized, то мютекс тут же автоматически разблокируется и будет свободен для захвата другой нитью.

Если же мютекс был занят, то наша нить будет стоять на месте и ждать когда он освободится.

— Так просто и так элегантно. Красивое решение.

— Ага. А как ты думаешь, что будет в этом случае?

Код Описание
class MyClass
{
private String name1 = "Оля";
private String name2 = "Лена";

public void swap()
{
synchronized (this)
{
String s = name1;
name1 = name2;
name2 = s;
}
}

public void swap2()
{
synchronized (this)
{
String s = name1;
name1 = name2;
name2 = s;
}
}
}
Методы swap и swap2 имеют один и тот же мютекс – объект this.

Что будет, если одна нить вызовет метод swap, а другая – метод swap2?

— Т.к. мютекс у них один, то второй нити придется ждать, пока первая нить выйдет из блока synchronized, поэтому проблем с одновременным доступом тут не будет.

— Молодец, Амиго! Верное решение!

Хотелось бы обратить твое внимание на то, что словом synchronized может быть помечен как кусок кода, так и метод. Вот что это значит:

Код Что происходит на самом деле
class MyClass
{
private static String name1 = "Оля";
private static String name2 = "Лена";

public synchronized void swap()
{
String s = name1;
name1 = name2;
name2 = s;
}

public static synchronized void swap2()
{
String s = name1;
name1 = name2;
name2 = s;
}
}
class MyClass
{
private static String name1 = "Оля";
private static String name2 = "Лена";

public void swap()
{
synchronized (this)
{
String s = name1;
name1 = name2;
name2 = s;
}
}

public static void swap2()
{
synchronized (MyClass.class)
{
String s = name1;
name1 = name2;
name2 = s;
}
}
}
Комментарии (13)
ЧТОБЫ ПОСМОТРЕТЬ ВСЕ КОММЕНТАРИИ ИЛИ ОСТАВИТЬ КОММЕНТАРИЙ,
ПЕРЕЙДИТЕ В ПОЛНУЮ ВЕРСИЮ
Roman Уровень 74
15 апреля 2025
Синхронизация потоков. Оператор synchronized в Java. https://javarush.com/groups/posts/1994-sinkhronizacija-potokov-operator-synchronized
Денис Уровень 66
24 февраля 2025
Сад-огород - единственная из представленных задач, которую решил самостоятельно и с 1-й попытки.
Артем Иевлев Уровень 115
12 декабря 2024
Для тех кто затрудняется в решении задач "МВФ" и "Синхронизированный президент" советую почитать про ленивую инициализацию синглтона ( https://javarush.com/groups/posts/2365-patternih-proektirovanija-singleton )
Руслан Никитин Уровень 109
11 сентября 2024

synchronized (this)
может не мьютекс, а монитор?!
Андрей Уровень 10
11 февраля 2025
вроде это одно и то же
Никита Уровень 74
4 июня 2025
Вещи похожие, но не одинаковые: Мютекс это низкоуровневая штука, которая умеет только блокировать объект. Монитор же высокоуровневый, он может не только блокировать, но еще и уведомлять потоки (нити). В synchronized используется именно монитор. А аналогом мютекса является ReentrantLock.
Никита Уровень 74
4 июня 2025
Вот такую табличку можно составить
Олег Уровень 106 Expert
15 июля 2024
Я ничего не понял
Олег Уровень 79 Expert
6 июля 2023
Странная эта задачка МВФ, как можно догадаться сравнивать с null входную переменную....????? хотя......
Константин Уровень 81
17 сентября 2024
Если посмотреть видео из https://javarush.com/groups/posts/1993 предыдущих лекций на 1:19:34 будет ответ.
Екатерина Уровень 70 Expert
8 сентября 2022
Меня одной всю дорогу адско бесит оформление кода в лекциях? 1. Он нечитаем 2. Он не иерархичен визуально 3. Строка текста(swap пример) занимает больше места чем код. збс - http://joxi.ru/ZrJJZ7RtQEDDar 4. Его нельзя удобно скопировать по кнопке, как есть на практически всех ресурсах что я юзаю, кроме данного профильного для обучения...... 5. Крупный шрифт, это хорошо. Обычно для презентационных сайтов юзают 16. Тут код оформлен 17, имхо - дико неудобно когда нужно посмотреть весь объем кода, и под рукой нет ИДЕ. Есть куда готовых нормальных паков, открытых, почем бы не заюзать их?
Андрей Уровень 69 Expert
8 июня 2022
Какой же я невнимательный сегодня, сидел думал, почему первый и последующие примеры не работают. Сделал 2 объекта и тестил, не получалось, пошел во все тяжкие меняя код, начал подозревать, что - то не то сделал с объектами, когда полям поставил статик, пошел читать текст еще раз, а том черным по белому))) Когда какой-то нити нужен общий для всех нитей объект, она проверяет мютекс, связанный с этим объектом. Один объект создавать в примерах нужно + 2 потока. Как я этого не заметил? Слип наверное не менее 8 часов нужен)))
I'm Siberian Уровень 109 Expert
14 сентября 2024
В задаче 1701 как раз в майне для примера и было

new NoteThread().start();
new NoteThread().start();