从这个问题How to understand the “non-fair” mode of ReentrantReadWriteLock?,我认为所有线程都有同样的机会获得锁定,无论哪个先出现。
所以我编写这段代码来测试它:
public static void main(String[] args) {
ReentrantReadWriteLock lock = new ReentrantReadWriteLock(true);
final ReadLock readLock = lock.readLock();
final WriteLock writeLock = lock.writeLock();
// hold the write lock 3s at first
new Thread() {
public void run() {
writeLock.lock();
System.out.println(Thread.currentThread().getName() + " got the write lock");
quietSleep(3);
writeLock.unlock();
System.out.println(Thread.currentThread().getName() + " released the write lock");
};
}.start();
// a thread want to get the read lock 1s later
new Thread() {
public void run() {
quietSleep(1);
readLock.lock();
System.out.println(Thread.currentThread().getName() + " got the read lock");
};
}.start();
// 1000 threads want to get the write lock 2s later
for (int i = 0; i < 1000; i++) {
new Thread() {
public void run() {
quietSleep(2);
writeLock.lock();
System.out.println(Thread.currentThread().getName() + " got the write lock");
};
}.start();
}
}
private static void quietSleep(int seconds) {
try {
Thread.sleep(seconds * 1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
首先,有一个线程获得写锁定,并保持3秒。在此期间,线程想要获取读锁定,然后1000个线程想要获得写锁定。
由于ReentrantReadWriteLock默认使用非公平模式,我认为写线程有很好的机会获得写锁定。但我运行了很多次,每次阅读线程都赢了!
输出结果为:
Thread-0 got the write lock
Thread-0 released the write lock
Thread-1 got the read lock
我是否理解“非公平”错误?
更新 根据paxdiablo的回答,我将我的代码修改为:
new Thread() {
public void run() {
quietSleep(1);
writeLock.lock();
System.out.println(Thread.currentThread().getName() + " got the write lock");
};
}.start();
for (int i = 0; i < 1000; i++) {
new Thread() {
public void run() {
quietSleep(2);
readLock.lock();
System.out.println(Thread.currentThread().getName() + " got the read lock");
};
}.start();
}
现在有一个线程想要写锁定,而1000个读取线程想要读锁定。但输出是:
Thread-0 got the write lock
Thread-0 released the write lock
Thread-1 got the write lock
似乎它仍然是“先到先得”。
答案 0 :(得分:3)
非公平只是意味着它不必以排队的方式分发锁(先到先得)。它没有其他保证将如何分发。实际上,如果需要,它可能仍然以排队的方式将它们移出。
可能是因为多个读者可以同时拥有锁定,但是如果作者得到了锁定,所有读者和作者都被阻止了。
我曾经不得不在很久以前实现一个读写器互斥体,它有多种模式,具体取决于你需要实现的目标:
听起来第一个是你的系统可能正在做的事情(我说“可能”,因为尽管有线程特性,你的代码可能会确定性地运行,即每次都是相同的)。
如果您想了解公平与非公平之间的区别,请尝试以下方法。
在公平模式下,它应该是RWRRRRRRRRRR
。这是因为除了第一个读锁之外的所有锁都将等到获得并释放写锁(写入先行因为这是公平的)。
在非公平模式下,您可能会看到RRRRRRRRRRRW
,读锁可能都被允许在写锁前面跳转,因为它们不会干扰第一次读锁,公平性被诅咒: - )