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

Что такое write head lock?

1.3 Junior🔥 191 комментариев
#Soft Skills и карьера

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

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

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

Write Head Lock в многопоточности и базах данных

Write Head Lock — это механизм синхронизации, используемый для управления конкурентным доступом к ресурсам (обычно файлам или данным в памяти) в многопоточной среде. Главная идея: разрешить одновременно несколько читателей, но только одного писателя, и не позволять читателям и писателям работать одновременно.

ReadWriteLock в Java

Это реализация паттерна write head lock в стандартной библиотеке Java:

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

public class ReadWriteLockExample {
    private ReadWriteLock lock = new ReentrantReadWriteLock();
    private int counter = 0;
    
    // Метод для чтения
    public int read() {
        lock.readLock().lock();
        try {
            System.out.println(Thread.currentThread().getName() + " читает: " + counter);
            Thread.sleep(1000); // Имитация долгого чтения
            return counter;
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
        } finally {
            lock.readLock().unlock();
        }
        return -1;
    }
    
    // Метод для записи
    public void write(int value) {
        lock.writeLock().lock();
        try {
            System.out.println(Thread.currentThread().getName() + " пишет: " + value);
            Thread.sleep(1000); // Имитация долгой записи
            counter = value;
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
        } finally {
            lock.writeLock().unlock();
        }
    }
    
    public static void main(String[] args) {
        ReadWriteLockExample example = new ReadWriteLockExample();
        
        // Несколько читателей могут работать одновременно
        new Thread(() -> example.read(), "Reader-1").start();
        new Thread(() -> example.read(), "Reader-2").start();
        
        // Писатель будет ждать, пока читатели завершат работу
        new Thread(() -> example.write(42), "Writer-1").start();
    }
}

Сравнение: Synchronized vs ReadWriteLock

Synchronized (простой подход):

public synchronized int read() {
    return counter; // Только один поток за раз
}

public synchronized void write(int value) {
    counter = value; // Только один поток за раз
}
// Проблема: читатели блокируют друг друга, хотя это неопасно

ReadWriteLock (оптимизированный подход):

public int read() {
    lock.readLock().lock();
    try {
        return counter; // Несколько читателей одновременно
    } finally {
        lock.readLock().unlock();
    }
}

Write Head Lock в базах данных

PostgreSQL и MySQL используют write head lock для управления конфликтами:

// В JDBC с блокировкой на запись
Connection conn = DriverManager.getConnection("jdbc:postgresql://localhost/mydb");
conn.setAutoCommit(false);
conn.setTransactionIsolation(Connection.TRANSACTION_SERIALIZABLE);

Statement stmt = conn.createStatement();
// SELECT FOR UPDATE блокирует выбранные строки от других писателей
stmt.execute("SELECT * FROM users WHERE id = 1 FOR UPDATE");

// Теперь никто другой не может обновить эту строку
stmt.execute("UPDATE users SET name = 'New Name' WHERE id = 1");

conn.commit();
conn.close();

Сценарий конфликта

Время | Reader-1    | Reader-2    | Writer-1      | counter
------|-------------|-------------|---------------|--------
0     | readLock()  |             |               | 0
1     |             | readLock()  |               | 0 (оба читают)
2     |             |             | writeLock()   | 0 (ждёт)
3     | readUnlock()| readUnlock()| получит lock  | 0
4     |             |             | write(42)     | 42
5     |             |             | writeUnlock() | 42

Практический пример: кэш с read/write lock

public class CacheWithReadWriteLock<K, V> {
    private final Map<K, V> cache = new HashMap<>();
    private final ReadWriteLock lock = new ReentrantReadWriteLock();
    
    public V get(K key) {
        lock.readLock().lock();
        try {
            return cache.get(key); // Несколько потоков могут читать одновременно
        } finally {
            lock.readLock().unlock();
        }
    }
    
    public void put(K key, V value) {
        lock.writeLock().lock();
        try {
            cache.put(key, value); // Только один поток может писать
        } finally {
            lock.writeLock().unlock();
        }
    }
    
    public void invalidate(K key) {
        lock.writeLock().lock();
        try {
            cache.remove(key);
        } finally {
            lock.writeLock().unlock();
        }
    }
    
    public static void main(String[] args) {
        CacheWithReadWriteLock<String, String> cache = new CacheWithReadWriteLock<>();
        cache.put("name", "John");
        
        // Несколько читателей
        for (int i = 0; i < 5; i++) {
            new Thread(() -> {
                System.out.println(cache.get("name"));
            }).start();
        }
        
        // Один писатель
        new Thread(() -> cache.put("name", "Jane")).start();
    }
}

Когда использовать write head lock

  • Частое чтение, редкая запись: кэши, конфигурация
  • Высокая конкурентность чтения: многопользовательские системы
  • Обновление коллекций: thread-safe вспомогательные структуры

Производительность

  • ReadWriteLock медленнее, чем Synchronized, если мало читателей
  • ReadWriteLock быстрее при много читателей, мало писателей (типичный кэш)
  • Дополнительный overhead на управление двумя блокировками