gpt4 book ai didi

java - 重入读写锁。读写优先

转载 作者:塔克拉玛干 更新时间:2023-11-02 08:48:25 24 4
gpt4 key购买 nike

我研究 ReentrantReadWriteLock

来自 java 文档的片段:

The thread will not acquire the read lock until after the oldest currently waiting writer thread has acquired and released the write lock

据我了解。

阅读时长- 1个时间单位

写入时长- 3个时间单位

  1. 时间 0 - 获得写锁
  2. 时间 1 - 读锁尝试读
  3. 时间 2 - 写锁尝试写

因此我期望以下顺序:

  1. 先写
  2. 第二次写
  3. 阅读

我的实验代码:

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

因此我得到

  1. 先写
  2. 阅读
  3. 第二次写

为什么我会得到这个结果?

是否可以打破 FIFO 顺序?

更新

请比较 java 文档中的两个兄弟片段(关于公平模式):

首先

尝试获取公平读锁(不可重入)的线程将在持有写锁或有等待写入线程的情况下阻塞。直到当前最旧的等待写线程获得并释放写锁后,该线程才会获得读锁。当然,如果一个正在等待的写者放弃等待,留下一个或多个读者线程作为队列中最长的等待者,写锁空闲,那么这些读者将被分配读锁。

第二个:

尝试获取公平写锁(不可重入)的线程将阻塞,除非读锁和写锁都是空闲的(这意味着没有等待线程)。 (请注意,非阻塞 ReentrantReadWriteLock.ReadLock.tryLock() 和 ReentrantReadWriteLock.WriteLock.tryLock() 方法不遵守此公平设置,如果可能,将获取锁,而不管等待线程如何。)

我不完全理解那里所写内容的含义但是我看到 ReentrantReadWriteLock 使用不同的策略来获取读锁和写锁。我建议如果 java 文档中的政治相同,则不会写两个缩进。

ReadLock 可以共享锁。只有一个区别吗?

最佳答案

首先,ReentrantReadWriteLock 应该在公平模式下创建,以施加特定的锁获取顺序:

private static ReadWriteLock lock = new ReentrantReadWriteLock(true);

然后,javadoc非常清楚地描述了您的案例:

When constructed as fair, threads contend for entry using an approximately arrival-order policy. When the currently held lock is released either the longest-waiting single writer thread will be assigned the write lock, or if there is a group of reader threads waiting longer than all waiting writer threads, that group will be assigned the read lock.

由于您的读取线程比第二个写入线程等待的时间更长,因此它在写入线程之前获取锁。

关于java - 重入读写锁。读写优先,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23104012/

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