Вопрос проверяет понимание ключевого слова 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 или атомарные классы, которые могут предложить лучшую производительность и гибкость.