Логотип YeaHub

База вопросов

Собеседования

Тренажёр

База ресурсов

Обучение

Навыки

Войти

Выбери, каким будет IT завтра — вместе c нами!

YeaHub — это полностью открытый проект, призванный объединить и улучшить IT-сферу. Наш исходный код доступен для просмотра на GitHub. Дизайн проекта также открыт для ознакомления в Figma.

© 2026 YeaHub

AI info

Карта сайта

Документы

Медиа

Назад
Вопрос про Java: Java, synchronized, multithreading, concurrency, thread safety

Что такое synchronized?

Вопрос проверяет понимание ключевого слова synchronized в Java, которое используется для управления доступом нескольких потоков к общим ресурсам.

Короткий ответ

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

Длинный ответ

Ключевое слово synchronized в Java — это механизм синхронизации, который обеспечивает безопасность при работе с несколькими потоками (multithreading). Когда несколько потоков обращаются к общим данным (например, к полям объекта), одновременные операции чтения и записи могут привести к повреждению данных — это состояние называется "гонкой данных" (data race). synchronized решает эту проблему, гарантируя, что только один поток может выполнять синхронизированный участок кода в определённый момент времени.

Как это работает

Каждый объект в Java имеет связанный с ним внутренний "монитор" (или блокировку). Когда поток входит в synchronized метод или блок, он захватывает монитор объекта (для нестатических методов — монитор экземпляра this; для статических — монитор объекта класса Class). Если другой поток попытается войти в любой синхронизированный метод того же объекта, он будет заблокирован до тех пор, пока первый поток не освободит монитор (т.е. не выйдет из синхронизированного участка).

Способы применения

  • Синхронизированный метод: Ключевое слово добавляется в объявление метода. Весь метод становится синхронизированным.
  • Синхронизированный блок: Позволяет синхронизировать только часть метода, что может повысить производительность, уменьшая время удержания блокировки. В блоке явно указывается объект-монитор.

Пример кода

public class Counter {
    private int count = 0;

    // Синхронизированный метод
    public synchronized void increment() {
        count++; // Эта операция теперь атомарна
    }

    // Альтернатива: синхронизированный блок
    public void decrement() {
        synchronized (this) { // Используем монитор текущего объекта
            count--;
        }
    }

    public int getCount() {
        return count;
    }
}

// Использование в многопоточном контексте
public class Main {
    public static void main(String[] args) throws InterruptedException {
        Counter counter = new Counter();
        Thread t1 = new Thread(() -> {
            for (int i = 0; i < 1000; i++) counter.increment();
        });
        Thread t2 = new Thread(() -> {
            for (int i = 0; i < 1000; i++) counter.increment();
        });
        t1.start();
        t2.start();
        t1.join();
        t2.join();
        // Без synchronized результат мог бы быть меньше 2000
        System.out.println("Final count: " + counter.getCount()); // 2000
    }
}

В примере выше метод increment синхронизирован, поэтому операции count++ двух потоков не будут пересекаться, и итоговое значение гарантированно будет равно 2000. Без synchronized из-за гонки данных результат мог бы быть непредсказуемым.

Где применяется

synchronized используется везде, где требуется обеспечить потокобезопасность (thread safety) при работе с общими изменяемыми ресурсами в Java-приложениях. Типичные сценарии:

  • Изменение состояния объекта (как в примере с счётчиком).
  • Работа с коллекциями, которые не являются потокобезопасными по умолчанию (например, ArrayList, HashMap), когда их нужно использовать из нескольких потоков.
  • Реализация кэшей, пулов соединений или других структур данных, доступных из разных потоков.

Вывод: Используйте synchronized, когда вам нужно простое и надёжное решение для синхронизации доступа к общим ресурсам в многопоточном Java-приложении. Однако для сложных сценариев с высокой конкуренцией рассмотрите более продвинутые средства из пакета java.util.concurrent, такие как ReentrantLock или атомарные классы, которые могут предложить лучшую производительность и гибкость.

Уровень

  • Рейтинг:

    4

  • Сложность:

    5

Навыки

  • Java

    Java

Ключевые слова

#Java

#synchronized

#multithreading

#concurrency

#thread safety

Подпишись на Java Developer в телеграм