В чем разница между видами блокировок?
Комментарии (1)
Ответ сгенерирован нейросетью и может содержать ошибки
Разница между видами блокировок
Блокировки (locks) — это механизмы синхронизации, которые контролируют доступ к общим ресурсам в многопоточной среде и в базах данных. В Java существует несколько типов блокировок, каждая с собственными характеристиками и применением.
Типы блокировок
1. Реентерабельная блокировка (ReentrantLock)
import java.util.concurrent.locks.ReentrantLock;
ReentrantLock lock = new ReentrantLock();
public void criticalSection() {
lock.lock();
try {
// защищённый код
System.out.println("Одна критическая секция");
} finally {
lock.unlock();
}
}
// Один поток может захватить одну и ту же блокировку несколько раз
public void nested() {
lock.lock();
try {
System.out.println("Первое захватывание");
nestedLock(); // успешно — поток уже владеет блокировкой
} finally {
lock.unlock();
}
}
Преимущества: большой контроль, попытки захвата с timeout, fair-режим Недостатки: более сложна в использовании, чем synchronized
2. Synchronized (встроенная блокировка)
public synchronized void method() {
// код защищён встроенной блокировкой объекта
}
// Или на уровне блока
private final Object lock = new Object();
public void method() {
synchronized(lock) {
// критическая секция
}
}
Преимущества: просто, автоматическое освобождение, встроена в язык Недостатки: нет контроля над timeout, нет fair-режима
3. ReadWriteLock (Читающие и пишущие блокировки)
import java.util.concurrent.locks.ReadWriteLock;
import java.util.concurrent.locks.ReentrantReadWriteLock;
ReadWriteLock rwLock = new ReentrantReadWriteLock();
public void read() {
rwLock.readLock().lock();
try {
// несколько потоков могут одновременно читать
System.out.println(getData());
} finally {
rwLock.readLock().unlock();
}
}
public void write() {
rwLock.writeLock().lock();
try {
// только один поток может писать
setData("new value");
} finally {
rwLock.writeLock().unlock();
}
}
Преимущества: оптимизация для read-heavy сценариев Недостатки: сложнее обычной блокировки, может быть медленнее при частых writes
4. StampedLock (Java 8+, оптимизированная версия ReadWriteLock)
import java.util.concurrent.locks.StampedLock;
StampedLock lock = new StampedLock();
public void optimisticRead() {
long stamp = lock.tryOptimisticRead();
int value = data; // читаем без захвата блокировки
if (!lock.validate(stamp)) {
// данные были изменены, нужно переделать
stamp = lock.readLock();
try {
value = data;
} finally {
lock.unlockRead(stamp);
}
}
}
Преимущества: очень быстра для read-heavy операций Недостатки: требует copy при конфликте
5. Блокировки в базах данных
В СУБД (PostgreSQL, MySQL, Oracle):
-- Эксклюзивная (exclusive) блокировка
SELECT * FROM users WHERE id = 1 FOR UPDATE;
-- Совместная (shared) блокировка
SELECT * FROM users WHERE id = 1 FOR SHARE;
Сравнительная таблица
| Тип | Множественные читатели | Переиспользование потоком | Timeout | Fairness |
|---|---|---|---|---|
| synchronized | Нет | Да | Нет | Нет |
| ReentrantLock | Нет | Да | Да | Да |
| ReadWriteLock | Да (read) | Да | Да | Да |
| StampedLock | Да (read) | Нет | Нет | Нет |
Когда использовать что
- synchronized: простые случаи, когда производительность не критична
- ReentrantLock: когда нужен контроль (timeout, fairness)
- ReadWriteLock: когда много читателей и мало писателей
- StampedLock: extreme performance в read-heavy сценариях
Выбор блокировки зависит от паттерна доступа и требований к производительности приложения.