РЕПЕТИТОР математика физика информатика
Для школьников и студентов. Подтягивание пробелов. ЦЭ, ЦТ, ОГЭ, ЕГЭ.
Идет набор на ЛЕТО. Жмите для подробностей:)
32 of 1163 menu

Ключевое слово synchronized

Ключевое слово synchronized используется для управления доступом к общим ресурсам из нескольких потоков. Когда поток входит в синхронизированный блок или метод, он захватывает монитор объекта. Другие потоки, пытающиеся войти в этот же синхронизированный блок или метод, будут заблокированы до тех пор, пока первый поток не освободит монитор. Синхронизация может применяться к методам (экземплярным и статическим) или к отдельным блокам кода. В случае синхронизированного метода монитором является сам объект (для экземплярных методов) или объект класса (для статических методов). В случае синхронизированного блока монитор указывается явно в скобках после ключевого слова.

Синтаксис

// synchronized method public synchronized void methodName() { // code } // synchronized static method public static synchronized void methodName() { // code } // synchronized block synchronized (object) { // code }

Пример

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

public class Main { private static int counter = 0; public static void main(String[] args) throws InterruptedException { Thread t1 = new Thread(() -> { for (int i = 0; i < 1000; i++) { counter++; } }); Thread t2 = new Thread(() -> { for (int i = 0; i < 1000; i++) { counter++; } }); t1.start(); t2.start(); t1.join(); t2.join(); System.out.println("Counter: " + counter); } }

Результат выполнения кода может быть меньше 2000 из-за состояния гонки:

Counter: 1847

Пример

Теперь используем synchronized для защиты счётчика. Создадим синхронизированный метод:

public class Main { private static int counter = 0; public static synchronized void increment() { counter++; } public static void main(String[] args) throws InterruptedException { Thread t1 = new Thread(() -> { for (int i = 0; i < 1000; i++) { increment(); } }); Thread t2 = new Thread(() -> { for (int i = 0; i < 1000; i++) { increment(); } }); t1.start(); t2.start(); t1.join(); t2.join(); System.out.println("Counter: " + counter); } }

Теперь результат всегда будет корректным:

Counter: 2000

Пример

Давайте используем синхронизированный блок вместо синхронизированного метода. Это позволяет синхронизировать только критическую секцию:

public class Main { private static int counter = 0; private static final Object lock = new Object(); public static void main(String[] args) throws InterruptedException { Thread t1 = new Thread(() -> { for (int i = 0; i < 1000; i++) { synchronized (lock) { counter++; } } }); Thread t2 = new Thread(() -> { for (int i = 0; i < 1000; i++) { synchronized (lock) { counter++; } } }); t1.start(); t2.start(); t1.join(); t2.join(); System.out.println("Counter: " + counter); } }

Результат выполнения кода:

Counter: 2000

Смотрите также

  • ключевое слово volatile,
    которое обеспечивает видимость изменений переменной
  • ключевое слово static,
    которое определяет статические члены класса
  • ключевое слово final,
    которое запрещает изменение переменной или метода
  • ключевое слово this,
    которое ссылается на текущий объект
Мы используем cookie для работы сайта, аналитики и персонализации. Обработка данных происходит согласно Политике конфиденциальности.
принять все настроить отклонить