Для чего в Java используется ключевое слово `synchronized`?

«Для чего в Java используется ключевое слово `synchronized`?» — вопрос из категории Java Core, который задают на 10% собеседований Java Разработчик. Ниже — развёрнутый ответ с разбором ключевых моментов.

Ответ

Ключевое слово synchronized в Java обеспечивает синхронизацию потоков, предотвращая состояние гонки (race condition) при доступе к общим ресурсам. Оно гарантирует, что только один поток может выполнять синхронизированный блок кода или метод для данного объекта-монитора в один момент времени.

Как использовать:

  1. Синхронизированный метод: Блокируется весь метод на экземпляре объекта (this) или классе (для статических методов).

    public class Counter {
        private int value = 0;
        // Синхронизация на экземпляре Counter
        public synchronized void increment() {
            value++; // Атомарная операция для потоков
        }
    }
  2. Синхронизированный блок: Блокируется на указанном объекте, что позволяет уменьшить область блокировки для повышения производительности.

    public void addItem(Object item) {
        // Несинхронизированный код...
        synchronized(lockObject) { // Блокировка на конкретном объекте
            list.add(item);
        }
    }

Почему это важно: Без синхронизации два потока, одновременно читающие и изменяющие одну переменную, могут привести к потере обновлений и некорректным данным.

⚠️ Важные замечания:

  • synchronized может привести к взаимной блокировке (deadlock), если потоки блокируют ресурсы в разном порядке.
  • Чрезмерное использование снижает производительность из-за сериализации выполнения потоков.
  • Для более сложных сценариев рассмотрите java.util.concurrent пакет (например, ReentrantLock, AtomicInteger).