← Назад к вопросам

Как обеспечить блокировку

2.2 Middle🔥 121 комментариев
#ООП#Основы Java

Комментарии (1)

🐱
claude-haiku-4.5PrepBro AI22 мар. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

# Как обеспечить блокировку в Java

Блокировка (synchronization) — критический механизм для управления конкурентным доступом к ресурсам в многопоточных приложениях. Рассмотрим основные подходы:

1. Synchronized блоки

Синхронизация методов

public class Counter {
    private int count = 0;
    
    // Синхронизация всего метода
    public synchronized void increment() {
        count++;
    }
    
    public synchronized int getCount() {
        return count;
    }
}

Синхронизация блока кода

public class Counter {
    private int count = 0;
    private Object lock = new Object();
    
    public void increment() {
        synchronized(lock) {
            count++;
        }
    }
}

Блоки лучше методов, так как минимизируют время удержания блокировки.

2. ReentrantLock

Более гибкая альтернатива synchronized:

public class Counter {
    private int count = 0;
    private Lock lock = new ReentrantLock();
    
    public void increment() {
        lock.lock();
        try {
            count++;
        } finally {
            lock.unlock();
        }
    }
}

Преимущества ReentrantLock:

  • Возможность lock со спецификацией timeout
  • Условные переменные (Condition)
  • Поддержка fair locks
public void incrementWithTimeout() throws InterruptedException {
    if (lock.tryLock(5, TimeUnit.SECONDS)) {
        try {
            count++;
        } finally {
            lock.unlock();
        }
    }
}

3. AtomicInteger / AtomicReference

Для простых операций с примитивами используй atomic классы:

public class Counter {
    private AtomicInteger count = new AtomicInteger(0);
    
    public void increment() {
        count.incrementAndGet(); // Без synchronized!
    }
    
    public int getCount() {
        return count.get();
    }
}

Compare-and-swap (CAS) операции:

AtomicInteger counter = new AtomicInteger(0);
boolean success = counter.compareAndSet(0, 1); // Если значение 0, установить 1

4. ReadWriteLock

Для сценариев с множеством читателей и редкими писателями:

public class Cache {
    private ReadWriteLock lock = new ReentrantReadWriteLock();
    private Map<String, String> data = new HashMap<>();
    
    public String get(String key) {
        lock.readLock().lock();
        try {
            return data.get(key);
        } finally {
            lock.readLock().unlock();
        }
    }
    
    public void put(String key, String value) {
        lock.writeLock().lock();
        try {
            data.put(key, value);
        } finally {
            lock.writeLock().unlock();
        }
    }
}

5. Volatile

Для простых флагов видимости между потоками:

public class ShutdownFlag {
    private volatile boolean shutdown = false;
    
    public void shutdown() {
        shutdown = true; // Видимо всем потокам
    }
    
    public boolean isShutdown() {
        return shutdown;
    }
}

6. Semaphore

Для контроля доступа ограниченного числа потоков:

public class ConnectionPool {
    private Semaphore semaphore = new Semaphore(10); // Максимум 10 соединений
    
    public void useConnection() throws InterruptedException {
        semaphore.acquire();
        try {
            // Работа с соединением
        } finally {
            semaphore.release();
        }
    }
}

7. Лучшие практики

Избегай deadlock:

// Плохо - риск deadlock
synchronized(lock1) {
    synchronized(lock2) { }
}

// Хорошо - всегда один порядок
synchronized(lock1) {
    synchronized(lock2) { }
}

Минимизируй время блокировки:

// Плохо
synchronized void expensiveOperation() {
    doSomethingExpensive();
    updateCounter();
}

// Хорошо
void expensiveOperation() {
    doSomethingExpensive();
    synchronized(lock) {
        updateCounter();
    }
}

Заключение

Выбирайте инструмент блокировки на основе требований: synchronized для простых случаев, ReentrantLock для сложной логики, Atomic для примитивов, volatile для флагов, ReadWriteLock для read-heavy сценариев.

Как обеспечить блокировку | PrepBro