- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
从这个问题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();
}
}
一开始有一个线程拿到了写锁,并持有了3s。这段时间有1个线程想拿到读锁,然后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
看来还是“先到先得”。
最佳答案
不公平只是意味着它不必以排队的方式分发锁(先到先得)。它对将的分发方式不做任何其他保证。事实上,如果需要,它可能仍以排队的方式分发它们。
它可能更喜欢将锁分发给读者,因为多个读者可以同时拥有锁,但如果一个写者获得它,所有的读者和写者都会被阻止。
我曾经不得不在很久以前实现一个读/写互斥锁,它有多种模式,具体取决于您需要实现的目标:
听起来第一个是您的系统可能正在做的事情(我说“可能”是因为它可能是您的代码确定性地运行,尽管线程性质,即每次都相同).
如果您想了解公平与不公平之间的区别,请尝试以下操作。
在公平模式下,它应该是RWRRRRRRRRRR
。这是因为除了第一个读锁之外的所有锁都将等待,直到获得并释放写锁(写先进行,因为这是公平的)。
在非公平模式下,你可能会看到RRRRRRRRRRRRW
,读锁可能都被允许跳到写锁前面,因为它们不干扰第一个读锁,公平是该死的:-)
当然,公平的概念可能因作者而异。允许读取在写入之前偷偷摸摸但有限制的算法规则可能在其中。例如,一旦请求写锁,则只允许另外五个读锁在排在写锁后面之前偷偷通过。
我并不是说任何人都实现过,但它肯定是一个可行的选择,可以平衡效率与公平性。
关于java - ReentrantReadWriteLock 非公平时为什么写线程拿不到锁?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7962458/
我有一个应用程序倾向于在后台线程中执行很多数据库 Activity (下载大型数据库更新),而且这个过程经常使“UI线程”匮乏-我知道数据库是不定期发布的,但是所使用的@synchronized机制不
我正在创建一个程序,用户可以在从一组项目中选择的两个项目之间进行一系列投票。每次投票后,会显示集合中的两个新项目并对其进行投票,直到看到集合中的所有成员。 这是我的限制条件: 每个用户应该以不同的随机
我正在开发一个在线判断类型的系统,其中大约 100 个不受信任的可执行文件将同时运行并评估相同的输入数据。 我希望每个可执行文件都限制在预定义资源池的 CPU、内存、磁盘空间等的相等份额。例如,如果资
我正在从事一个关于 CFS 的项目。使用Ftrace跟踪Linux公平进程的全路径。 根据文档 https://lwn.net/Articles/370423/ . [tracing]# echo $
Semaphore 类概述 developer.android.com看起来不错 - 对于那些已经熟悉这些概念和术语的人来说。 我熟悉那里的一些首字母缩略词和其他行话(例如 FIFO、锁等),但其他的
我是一名优秀的程序员,十分优秀!