Ключевое слово synchronized в Java
Данная статья:
- написана командой Vertex Academy. Надеемся, что она Вам будет полезна. Приятного прочтения!
- это одна из статей из нашего "Самоучителя по Java"
Привет! В этой статье мы расскажем про ключевое слово synchronized.
- Эта тема связана с многопоточностью.
Что такое synchronized
Представим, что у нас есть два потока. Обрисуем ситуацию с потоками на аналогии с человеческой жизнью.
Каждый из них занимается своими делами.
Потом им обоим понадобились одни и те же данные, которые спрятаны за дверью:
Но мы не хотим, чтобы оба потока изменяли данные за дверью одновременно, потому что один может изменить одну часть по-одному, а второй по-другому . Поэтому, в одно время в ней должен находится только один поток.
Потоки пока про это не знают. Они думают, что могут зайти в дверь (например, в какой-нибудь метод нашей программы) тогда, когда им захочется.
Чтобы ограничить доступ к двери, и позволить только одному потоку находится там в какой-либо момент времени, мы используем ключевое слово synchronized.
Synchronized (с англ. "синхронизированный") - это ключевое слово, которое позволяет заблокировать доступ к методу или части кода, если его уже использует другой поток.
Если метод или объект "свободен" - поток может с ним работать:
Если же метод уже используется - поток просто ждет:
Пример
Существует два применения synchronized - для метода и для блока кода.
Для блока кода
Если Вам не нужно синхронизировать весь метод, а только его часть - например, объект, - можно использовать следующую форму модификатора synchronized:
В коде это может выглядеть так:
1 2 3 4 5 6 7 8 |
public void myMethod() { private Object key = new Object(); synchronized (key) { System.out.println("Hi I'm synchronized block!"); } } |
Для метода
Если Вы хотите синхронизировать доступ к целому методу - можете дописать "synchronized" перед названием метода:
1 2 3 |
synchronized void myMethod() { System.out.println("Hi I'm synchronized method!"); } |
Стоит заметить, что данный synchronized метод можно воспринимать так:
1 2 3 4 5 |
void myMethod() { synchronized(this) { System.out.println("Hi I'm synchronized method!"); } } |
Если бы он был статическим, то представление слегка поменялось бы на:
1 2 3 4 5 |
static void myMethod() { synchronized(MyObject.class) { System.out.println("Hi I'm synchronized method!"); } } |
Думаю, Вы заметили, что поменялись "ключи" синхронизации.
"Живые" примеры использования synchronized можно найти, например, в статье про реализации патерна программирования Singleton.
Стоит знать
Если Вы будете еще что-то читать про synchronized, Вы можете встретить такие термины:
- Монитор. Вы можете прочитать, что ключевое слово synchronized позволяет "войти в монитор объекта".
Монитор - это специальный объект, который следит за "состоянием" метода или объекта. Он смотрит, "занят" он или "свободен" в данный момент.
- Атомарный. Многие проблемы с потоками возникают тогда, когда два потока, используя один метод, мешают друг другу. Они могут менять значения переменных, которые использует другой поток.
Атомарный - значит "неделимый" - в том смысле, что операция может быть завершена одним потоком, и другой не может в ней ничего "напортить".
В чем же минус synchronized
- Недостатком использования synchronized является как раз то, что другие потоки вынуждены ждать, пока нужный объект или метод освободится. Это создает так называемый "bottle neck" ("узкое место") в программе - и скорость работы может пострадать. Поэтому, используйте synchronized с умом по мере необходимости 🙂
Надеемся, что наша статья была Вам полезна. Можно записаться к нам на курсы по Java на сайте.