ReentrantReadWriteLock. чтение и запись приобретают приоритет

Я исследую ReentrantReadWriteLock

фрагмент из документа Java:

Поток не получит блокировку чтения до тех пор, пока самый старый в настоящее время ожидающий поток записи не получит и не снимет блокировку записи

Таким образом, как я понял.

длительность чтения - 1 единица времени

продолжительность записи - 3 единицы времени

  1. время 0 - запись заблокирована
  2. время 1 - чтение блокировки попытка чтения
  3. время 2 - блокировка записи попробуйте написать

Таким образом я ожидаю следующую последовательность:

  1. сначала напиши
  2. вторая запись
  3. читать

мой экспериментальный код:

public class RWLockCalculator {
    static long initTime = System.currentTimeMillis();
    private static int calculatedValue = 0;
    private static ReadWriteLock lock = new ReentrantReadWriteLock();
    public void calculate(int value) {
        lock.writeLock().lock();
        try {           
            System.out.println("write lock acquired at "+ (System.currentTimeMillis()-RWLockCalculator.initTime));
            this.calculatedValue = 1;
            Thread.sleep(300);
        } catch (InterruptedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } finally {
            lock.writeLock().unlock();
        }
    }

    public int getCalculatedValue() {
        lock.readLock().lock();
        try {           
            System.out.println("read lock acquired at "+ (System.currentTimeMillis()-RWLockCalculator.initTime));
            Thread.sleep(100);
            return calculatedValue;
        } catch (InterruptedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
            return -1;
        } finally {
            lock.readLock().unlock();
        }
    }
}

class Test {
    public static void main(String[] args) throws InterruptedException {
        new WriteThread().start();
        Thread.sleep(100);
        new ReadThread().start();
        Thread.sleep(100);
        new WriteThread().start();

    }
}

class ReadThread extends Thread {
    @Override
    public void run() {
        System.out.println(new RWLockCalculator().getCalculatedValue() + ", " + (System.currentTimeMillis() - RWLockCalculator.initTime));
    }
}

class WriteThread extends Thread {
    @Override
    public void run() {
        new RWLockCalculator().calculate(99);
        System.out.println("I have written in  " + (System.currentTimeMillis() - RWLockCalculator.initTime));
    }
}

из:

write lock acquired at 0
I have written in  300
read lock acquired at 300
1, 400
write lock acquired at 400
I have written in  700

Таким образом я получаю

  1. сначала напиши
  2. читать
  3. вторая запись

Почему я получаю этот результат?

Можно ли нарушить порядок FIFO?

Обновить

Пожалуйста, сравните два фрагмента из java doc(о честном режиме):

первый

Поток, который пытается получить справедливую блокировку чтения (не реентерабельно), будет блокироваться, если либо удерживается блокировка записи, либо существует ожидающий поток записи. Поток не получит блокировку чтения до тех пор, пока самый старый в настоящее время ожидающий поток записи не получит и не снимет блокировку записи. Конечно, если ожидающий писатель откажется от своего ожидания, оставив один или несколько потоков считывателей самыми длинными официантами в очереди со свободной блокировкой записи, тогда этим считывателям будет назначена блокировка чтения.

второй:

Поток, который пытается получить справедливую блокировку записи (не реентерабельно), будет блокироваться, если и блокировка чтения, и блокировка записи не свободны (что подразумевает отсутствие ожидающих потоков). (Обратите внимание, что неблокирующие методы ReentrantReadWriteLock.ReadLock.tryLock() и ReentrantReadWriteLock.WriteLock.tryLock() не учитывают этот справедливый параметр и получат блокировку, если это возможно, независимо от ожидающих потоков.)

Я не до конца понимаю смысл написанного там Но я вижу, что ReentrantReadWriteLock использует разные политики для получения блокировки чтения и записи. Я полагаю, что, если бы политика была такой же в java doc, не написал бы два отступа.

ReadLock может делиться блокировками. Это только одно отличие?

1 ответ

Решение

Прежде всего, ReentrantReadWriteLock должен быть создан в честном режиме для наложения определенного порядка получения блокировки:

private static ReadWriteLock lock = new ReentrantReadWriteLock(true);

Затем Javadoc описывает ваш случай довольно четко:

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

Поскольку ваш поток чтения ждал дольше, чем второй поток записи, он получает блокировку перед потоком записи.

Другие вопросы по тегам