Looking for java Keywords? Try Ask4Keywords

Java Language Эксклюзивная запись / параллельный доступ для чтения


пример

Иногда требуется, чтобы процесс одновременно записывал и читал одни и те же «данные».

Интерфейс ReadWriteLock и его реализация ReentrantReadWriteLock позволяют получить шаблон доступа, который можно описать следующим образом:

  1. Может быть любое количество одновременных считывателей данных. Если есть хотя бы один доступ к читателю, доступ к записи невозможен.
  2. Данные могут быть не более одного отдельного автора. Если есть доступ к записи, то ни один читатель не может получить доступ к данным.

Реализация может выглядеть так:

import java.util.concurrent.locks.ReadWriteLock;
import java.util.concurrent.locks.ReentrantReadWriteLock;
public class Sample {

// Our lock. The constructor allows a "fairness" setting, which guarantees the chronology of lock attributions.
protected static final ReadWriteLock RW_LOCK = new ReentrantReadWriteLock();

// This is a typical data that needs to be protected for concurrent access
protected static int data = 0;

/** This will write to the data, in an exclusive access */
public static void writeToData() {
    RW_LOCK.writeLock().lock();
    try {
        data++;
    } finally {
        RW_LOCK.writeLock().unlock();
    }
}

public static int readData() {
    RW_LOCK.readLock().lock();
    try {
        return data;
    } finally {
        RW_LOCK.readLock().unlock();
    }
}

}

ПРИМЕЧАНИЕ 1. Этот точный вариант использования имеет более чистое решение с использованием AtomicInteger , но здесь описывается шаблон доступа, который работает независимо от того, что данные здесь представляют собой целое число, которое как вариант Atomic.

ПРИМЕЧАНИЕ 2 : Блокировка считывающей части действительно необходима, хотя она может выглядеть не так, как у обычного читателя. Действительно, если вы не блокируете читателя, любое количество вещей может пойти не так, в том числе:

  1. Запись примитивных значений не гарантируется атомарным на всех JVM, поэтому читатель мог видеть, например, только 32 бита из 64-битной записи, если data были 64-битным длинным типом
  2. Видимость записи из потока, который не выполнял его, гарантируется JVM только в том случае, если мы устанавливаем Happen Before relationship между write и reads. Эта связь устанавливается, когда и читатели, и писатели используют свои соответствующие блокировки, но не иначе
Java SE 8

Если требуется более высокая производительность, при определенных типах использования существует более быстрый тип блокировки, называемый StampedLock , который, среди прочего, реализует оптимистичный режим блокировки. Этот замок работает совсем иначе, чем ReadWriteLock , и этот образец не может быть транспонирован.