gpt4 book ai didi

java - ReentrantReadWriteLock 非公平时为什么写线程拿不到锁?

转载 作者:行者123 更新时间:2023-11-29 06:07:57 25 4
gpt4 key购买 nike

从这个问题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

看来还是“先到先得”。

最佳答案

不公平只是意味着它不必以排队的方式分发锁(先到先得)。它对的分发方式不做任何其他保证。事实上,如果需要,它可能以排队的方式分发它们。

它可能更喜欢将锁分发给读者,因为多个读者可以同时拥有锁,但如果一个写者获得它,所有的读者和写者都会被阻止。

我曾经不得不在很久以前实现一个读/写互斥锁,它有多种模式,具体取决于您需要实现的目标:

  • 更喜欢阅读器。
  • 喜欢作家。
  • 首选替代读者/作者。
  • 排队访问。

听起来第一个是您的系统可能正在做的事情(我说“可能”是因为它可能是您的代码确定性地运行,尽管线程性质,即每次都相同).


如果您想了解公平与不公平之间的区别,请尝试以下操作。

  • 让一个线程获得读锁,然后 hibernate 一分钟。
  • 在 hibernate 期间,让一个线程请求写锁并 hibernate 一分钟。
  • 然后进行十次尝试获取和释放读锁的循环。

在公平模式下,它应该是RWRRRRRRRRRR。这是因为除了第一个读锁之外的所有锁都将等待,直到获得并释放写锁(写先进行,因为这是公平的)。

在非公平模式下,你可能会看到RRRRRRRRRRRRW,读锁可能都被允许跳到写锁前面,因为它们不干扰第一个读锁,公平是该死的:-)


当然,公平的概念可能因作者而异。允许读取在写入之前偷偷摸摸但有限制的算法规则可能在其中。例如,一旦请求写锁,则只允许另外五个读锁在排在写锁后面之前偷偷通过。

我并不是说任何人都实现过,但它肯定是一个可行的选择,可以平衡效率与公平性。

关于java - ReentrantReadWriteLock 非公平时为什么写线程拿不到锁?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7962458/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com