Комментарии (1)
🐱
claude-haiku-4.5PrepBro AI22 мар. 2026 г.(ред.)
Ответ сгенерирован нейросетью и может содержать ошибки
# Где используют synchronized
Synchronized (синхронизация) используется для контроля доступа к общим ресурсам в многопоточной среде. Это механизм для предотвращения race conditions и обеспечения consistency данных.
Когда нужна синхронизация
1. Общие переменные, изменяемые несколькими потоками
public class Counter {
private int count = 0; // Общая переменная
// БЕЗ synchronized - race condition!
public void increment() {
count++; // Три операции: прочитай, прибавь, запиши
}
// С synchronized - безопасно
public synchronized void incrementSafe() {
count++; // Атомарно для других потоков
}
public synchronized int getCount() {
return count;
}
}
Без synchronized другой поток может прочитать count посередине операции increment(), приводя к потере обновлений.
2. Коллекции (List, Map, Set)
Стандартные коллекции не потокобезопасны:
// БЕЗ синхронизации - проблемы при параллельном доступе
List<String> list = new ArrayList<>();
for (int i = 0; i < 100; i++) {
new Thread(() -> list.add("item")).start();
}
// ConcurrentModificationException может быть выброшено
// С synchronized wrapper
List<String> syncList = Collections.synchronizedList(new ArrayList<>());
for (int i = 0; i < 100; i++) {
new Thread(() -> syncList.add("item")).start();
}
// ИЛИ используй ConcurrentHashMap, CopyOnWriteArrayList
Map<String, Integer> map = new ConcurrentHashMap<>();
List<String> cowList = new CopyOnWriteArrayList<>();
3. Кэширование и ленивая инициализация
public class Singleton {
private static Singleton instance = null;
// Double-checked locking паттерн
public static Singleton getInstance() {
if (instance == null) { // Первая проверка без блокировки
synchronized (Singleton.class) { // Блокируем только при необходимости
if (instance == null) { // Вторая проверка внутри synchronized
instance = new Singleton();
}
}
}
return instance;
}
}
// Более простой способ в современной Java
public class SimpleSingleton {
private static final SimpleSingleton instance = new SimpleSingleton();
public static SimpleSingleton getInstance() {
return instance; // Инициализируется при загрузке класса
}
}
4. Пулы ресурсов и connection pools
public class ConnectionPool {
private Queue<Connection> available = new LinkedList<>();
public synchronized Connection getConnection() throws InterruptedException {
while (available.isEmpty()) {
wait(); // Ждем, пока освободится соединение
}
Connection conn = available.poll();
notifyAll(); // Уведомляем ждущие потоки
return conn;
}
public synchronized void releaseConnection(Connection conn) {
available.offer(conn);
notifyAll(); // Пробуждаем один ждущий поток
}
}
5. Producer-Consumer паттерн
public class Buffer {
private Queue<String> queue = new LinkedList<>();
private int maxSize = 10;
public synchronized void produce(String item) throws InterruptedException {
while (queue.size() >= maxSize) {
wait(); // Ждем, если буфер полон
}
queue.offer(item);
notifyAll(); // Уведомляем consumer
}
public synchronized String consume() throws InterruptedException {
while (queue.isEmpty()) {
wait(); // Ждем, если буфер пуст
}
String item = queue.poll();
notifyAll(); // Уведомляем producer
return item;
}
}
6. Счетчики и статистика
public class RequestCounter {
private int totalRequests = 0;
private int successfulRequests = 0;
private int failedRequests = 0;
public synchronized void recordRequest(boolean success) {
totalRequests++;
if (success) {
successfulRequests++;
} else {
failedRequests++;
}
}
public synchronized void printStats() {
System.out.println("Total: " + totalRequests);
System.out.println("Success: " + successfulRequests);
System.out.println("Failed: " + failedRequests);
}
}
Уровни синхронизации
Синхронизация методов
public class SyncMethod {
// Синхронизирует весь метод
public synchronized void method() {
// Только один поток может выполнять одновременно
}
// Это эквивалентно:
public void methodManual() {
synchronized (this) {
// Код
}
}
}
Синхронизация блока
public class SyncBlock {
private List<String> list = new ArrayList<>();
private int counter = 0;
public void mixedAccess() {
// Unsynchronized код
String data = fetchData();
// Только этот блок синхронизирован
synchronized (this) {
list.add(data);
counter++;
}
// Unsynchronized код
processResult();
}
}
Статические synchronized методы
public class StaticSync {
private static int sharedCounter = 0;
// Синхронизирует весь класс (не инстанс)
public static synchronized void incrementGlobal() {
sharedCounter++;
}
// Эквивалентно:
public static void incrementGlobalManual() {
synchronized (StaticSync.class) {
sharedCounter++;
}
}
}
Проблемы с synchronized
1. Deadlock
public class DeadlockExample {
private Object lock1 = new Object();
private Object lock2 = new Object();
public void method1() {
synchronized (lock1) {
Thread.sleep(100); // Имитируем работу
synchronized (lock2) { // Может зависнуть
// Код
}
}
}
public void method2() {
synchronized (lock2) {
Thread.sleep(100);
synchronized (lock1) { // Может зависнуть
// Код
}
}
}
}
2. Низкая производительность при высокой конкуренции
// При 100+ потоков, synchronized становится узким местом
public class SlowCounter {
private int count = 0;
public synchronized void increment() {
count++;
}
}
// Лучше использовать AtomicInteger
public class FastCounter {
private AtomicInteger count = new AtomicInteger(0);
public void increment() {
count.incrementAndGet(); // Неблокирующая операция
}
}
Когда использовать что
// Простые счетчики → AtomicInteger, AtomicLong
private AtomicInteger counter = new AtomicInteger();
// Коллекции → ConcurrentHashMap, CopyOnWriteArrayList
Map<String, String> map = new ConcurrentHashMap<>();
// Сложная синхронизация → synchronized или ReentrantLock
private final Object lock = new Object();
// Множество потоков с ожиданием → CountDownLatch, Semaphore, Barrier
CountDownLatch latch = new CountDownLatch(10);
// Новые потоки → CompletableFuture, Project Loom (Virtual Threads)
CompletableFuture.runAsync(() -> {
// Код в другом потоке
});
Вывод
Synchronized используется для:
- Защиты общих изменяемых данных
- Обеспечения atomicity операций
- Реализации паттернов wait/notify
- Синхронизации доступа к коллекциям
Но в современной Java часто лучше выбрать:
- Атомарные классы (AtomicInteger, AtomicReference)
- Потокобезопасные коллекции (ConcurrentHashMap, CopyOnWriteArrayList)
- Блокирующие очереди (BlockingQueue)
- Async/Future паттерны (CompletableFuture, Project Loom)