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

В чем разница между видами блокировок?

2.4 Senior🔥 151 комментариев
#JVM и управление памятью#Базы данных и SQL#Многопоточность

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

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

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

Разница между видами блокировок

Блокировки (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;

Сравнительная таблица

ТипМножественные читателиПереиспользование потокомTimeoutFairness
synchronizedНетДаНетНет
ReentrantLockНетДаДаДа
ReadWriteLockДа (read)ДаДаДа
StampedLockДа (read)НетНетНет

Когда использовать что

  • synchronized: простые случаи, когда производительность не критична
  • ReentrantLock: когда нужен контроль (timeout, fairness)
  • ReadWriteLock: когда много читателей и мало писателей
  • StampedLock: extreme performance в read-heavy сценариях

Выбор блокировки зависит от паттерна доступа и требований к производительности приложения.

В чем разница между видами блокировок? | PrepBro