Что такое ReadWriteLock в Java?

Ответ

ReadWriteLock — это интерфейс в пакете java.util.concurrent.locks, который реализует шаблон разделения блокировок для чтения и записи. Он позволяет нескольким потокам одновременно читать общий ресурс, но требует эксклюзивной блокировки для операций записи.

Основные принципы:

  • Блокировка чтения (ReadLock): Может быть получена несколькими потоками одновременно, но только при отсутствии активной блокировки записи.
  • Блокировка записи (WriteLock): Эксклюзивна. Когда она удерживается, никакие другие блокировки (ни на чтение, ни на запись) не могут быть получены.

Типичное использование (на примере ReentrantReadWriteLock):

import java.util.concurrent.locks.ReadWriteLock;
import java.util.concurrent.locks.ReentrantReadWriteLock;

public class SharedResource {
    private final ReadWriteLock rwLock = new ReentrantReadWriteLock();
    private Object data;

    public Object read() {
        rwLock.readLock().lock();
        try {
            // Безопасное чтение данных несколькими потоками
            return data;
        } finally {
            rwLock.readLock().unlock(); // Важно освобождать в finally
        }
    }

    public void write(Object newData) {
        rwLock.writeLock().lock();
        try {
            // Эксклюзивная запись. Другие читатели/писатели ждут.
            this.data = newData;
        } finally {
            rwLock.writeLock().unlock();
        }
    }
}

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

  • Повышение производительности в сценариях с частым чтением и редкой записью.
  • Обеспечение целостности данных при записи.

Недостатки и риски:

  • Голодание писателей: При непрерывном потоке читателей писатель может никогда не получить доступ.
  • Снижение производительности, если операции чтения короткие, а накладные расходы на управление блокировками высоки.
  • Реализация ReentrantReadWriteLock может быть нечестной (по умолчанию), что может привести к неопределенному порядку доступа. Честный режим (fair=true) гарантирует порядок, но снижает пропускную способность.

Ответ 18+ 🔞

Давайте разберём эту штуку, которая называется ReadWriteLock. Представь себе библиотеку, блядь. Все могут зайти и читать книги одновременно — тихо, мирно, никто никому не мешает. Но если какой-то мудак решит взять и переписать каталог или, хуле, новую полку прибить — всем остальным придётся нахуй подождать, пока он закончит. Вот примерно так это и работает, только в коде.

Основная фишка в том, что читать могут многие, а писать — только один, и то когда все читатели разойдутся. Как очередь в сортир на вечеринке: посрать заходит один, а просто пописать — хоть десять сразу, если кабинки отдельные.

Вот смотри, как это выглядит в деле:

import java.util.concurrent.locks.ReadWriteLock;
import java.util.concurrent.locks.ReentrantReadWriteLock;

public class SharedResource {
    private final ReadWriteLock rwLock = new ReentrantReadWriteLock();
    private Object data;

    public Object read() {
        rwLock.readLock().lock(); // Захватил замок на чтение
        try {
            // Тут безопасно читаешь данные, хоть всей толпой
            return data;
        } finally {
            rwLock.readLock().unlock(); // ОБЯЗАТЕЛЬНО отпусти, а то все зависнут!
        }
    }

    public void write(Object newData) {
        rwLock.writeLock().lock(); // А вот тут уже эксклюзив — все остальные на паузе
        try {
            this.data = newData; // Пишешь, и никто не мешает
        } finally {
            rwLock.writeLock().unlock(); // И тоже отпускаешь, конечно
        }
    }
}

Плюсы, блядь, очевидны: если у тебя данные чаще читают, чем меняют — производительность летит в космос, потому что потоки не толкаются локтями.

А теперь подводные ебучки, потому что без них никуда:

  1. Писатель может заждаться, как дурак. Если читатели непрерывным потоком ломятся — бедолага с блокировкой на запись будет стоять вечно, как последний лох. Это называется голодание писателей.
  2. Если чтение — дело пяти наносекунд, а возня с блокировками занимает больше — зачем вообще эта петрушка? Иногда проще synchronized впендюрить и не париться.
  3. Реализация ReentrantReadWriteLock по умолчанию нечестная — кто первый успел, того и тапки. Можно включить честный режим (fair=true), но тогда все будут строиться в очередь, и общая скорость просядет, как шарик от подшипника в говне.

Короче, инструмент охуенный, но только если твой сценарий подходит. Как молоток: гвозди забивать — идеально, а вот яйца на сковородке им лучше не разбивать.