Я исследую ReentrantReadWriteLock
фрагмент из java-документа:
Поток не получит блокировку чтения до тех пор, пока самый старый в настоящее время ожидающий поток записи не получит и не освободит блокировку записи.
Таким образом, как я понял.
длительность чтения – 1 единица времени
длительность записи – 3 единицы времени
- время 0 - получена блокировка записи
- время 1 - чтение блокировки попробовать чтение
- время 2 - запись блокировки попробовать запись
Таким образом, я ожидаю следующую последовательность:
- сначала напиши
- вторая запись
- читать
код моего эксперимента:
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
Таким образом я получаю
- сначала напиши
- читать
- вторая запись
Почему я получаю этот результат?
Можно ли нарушить порядок FIFO?
Обновлять
Пожалуйста, сравните два родственных фрагмента из java-документа (о справедливом режиме):
первый
Поток, пытающийся получить блокировку справедливого чтения (без повторного входа), заблокируется, если удерживается блокировка записи или существует ожидающий поток записи. Поток не получит блокировку чтения до тех пор, пока самый старый в настоящее время ожидающий поток записи не получит и не освободит блокировку записи. Конечно, если ожидающий модуль записи отказывается от своего ожидания, оставляя один или несколько потоков чтения в качестве самых длинных ожидающих в очереди со свободной блокировкой записи, тогда этим читателям будет назначена блокировка чтения.
второй:
Поток, который пытается получить справедливую блокировку записи (без повторного входа), будет заблокирован, если и блокировка чтения, и блокировка записи не свободны (что подразумевает отсутствие ожидающих потоков). (Обратите внимание, что неблокирующие методы ReentrantReadWriteLock.ReadLock.tryLock() и ReentrantReadWriteLock.WriteLock.tryLock() не учитывают эту справедливую настройку и получат блокировку, если это возможно, независимо от ожидающих потоков.)
Я не совсем понимаю смысл того, что там написано. Но я вижу, что ReentrantReadWriteLock
использует разные политики для получения блокировки чтения и блокировки записи. Я предполагаю, что если бы политика в java-документе была такой же, не было бы двух отступов.
ReadLock может совместно использовать блокировки. Это только одно отличие?