我研究 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 doc 中的两个兄弟片段(关于公平模式):
第一的
如果持有写锁或存在等待写入线程,则尝试获取公平读锁(不可重入)的线程将阻塞。直到当前等待的最早的写线程获得并释放写锁之后,该线程才会获得读锁。当然,如果一个等待的写入者放弃它的等待,留下一个或多个读取线程作为队列中最长的等待者,并且没有写入锁,那么这些读取器将被分配读取锁。
第二:
除非读锁和写锁都空闲(这意味着没有等待线程),否则试图获取公平写锁(不可重入)的线程将阻塞。(请注意,非阻塞 ReentrantReadWriteLock.ReadLock.tryLock() 和 ReentrantReadWriteLock.WriteLock.tryLock() 方法不遵守此公平设置,如果可能,将获取锁,而不管等待线程。)
我不完全理解那里写的意思但是我看到ReentrantReadWriteLock
使用不同的策略来获取读锁和写锁。我建议如果 java doc 中的政治相同,就不会写两个缩进。
ReadLock 可以共享锁。难道只有一个区别吗?