Что такое 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-приложения.