Что такое synchronized в Java?
synchronized в Java — это ключевое слово, которое используется для организации синхронизированного (потокобезопасного) доступа к ресурсам в многопоточном программировании. Оно гарантирует, что только один поток может одновременно выполнять определённый блок кода или метод, помеченный как synchronized.
Это один из самых простых и распространённых способов избежать race condition.
🔐 Что делает synchronized
synchronized блокирует монитор (monitor) — объектную блокировку — чтобы другие потоки не могли войти в этот же критический участок кода, пока текущий поток его не покинет.
📌 Способы использования
1. Синхронизация метода
Экземплярный метод (synchronized на this):
public synchronized void increment() {
counter++;
}
Эквивалентно:
public void increment() {
synchronized (this) {
counter++;
}
}
🔒 Блокировка происходит на текущем объекте (this).
Статический метод (synchronized на Class):
public static synchronized void log() {
System.out.println("Logged");
}
Эквивалентно:
public static void log() {
synchronized (MyClass.class) {
System.out.println("Logged");
}
}
🔒 Блокировка происходит на объекте Class, представляющем данный класс.
2. Синхронизированный блок
Позволяет синхронизировать только часть метода, а не весь:
public void write() {
// несинхронизированный код
synchronized(lockObject) {
// критическая секция
}
}
Плюсы:
-
Более гибко и производительно, чем синхронизация всего метода.
-
Можно использовать разные объекты-блокировки.
🧠 Как это работает
-
Когда поток входит в synchronized-блок или метод, он захватывает монитор объекта.
-
Все другие потоки, которые хотят войти в блок, синхронизированный по тому же объекту, будут заблокированы, пока первый поток не выйдет из него.
-
Когда поток выходит — монитор освобождается, и следующий поток может продолжить.
⚠️ Важно
-
Блокировка всегда привязана к объекту (this, кастомный lock, Class и т. д.).
-
Если синхронизироваться по разным объектам, защита не сработает.
-
Не синхронизируйтесь по изменяемым объектам — можно случайно потерять защиту (lock = new Object() в другом потоке).
-
Если неосторожно использовать synchronized, можно получить deadlock.
📊 Пример с несколькими потоками
public class Counter {
private int count = 0;
public synchronized void increment() {
count++;
}
public synchronized int get() {
return count;
}
}
→ Только один поток за раз сможет вызвать increment() или get().
🛠 Альтернатива synchronized
Java предлагает более гибкие и масштабируемые способы синхронизации:
-
ReentrantLock из java.util.concurrent.locks — с ручным управлением блокировками.
-
AtomicInteger, AtomicReference и др. — для атомарных операций.
-
synchronized подходит для простых случаев, но в сложных сценариях лучше использовать более современные инструменты.
Итого
Особенность | Описание |
---|---|
Ключевое слово | synchronized |
--- | --- |
Цель | Синхронизированный (потокобезопасный) доступ к ресурсу |
--- | --- |
Работает через | Мониторы (блокировки объектов) |
--- | --- |
Уровни применения | Методы и блоки кода |
--- | --- |
Основные риски | Deadlock, снижение производительности |
--- | --- |
Альтернатива | ReentrantLock, атомарные типы, volatile, Semaphore и др. |
--- | --- |
synchronized — это простой способ защитить критические секции кода от одновременного доступа, особенно в начальных этапах проектирования многопоточного Java-приложения.