java - ReentrantLock 条件的优先级
问题描述
问题:我有一组Thread
s,其中一些在获取 时必须优先于其他ReentrantLock
。
解决方案:我可以想象有一个有 2 个队列的公平 :和. 点是之前发出的信号。考虑到公平性,一定会发生sblocked in总是先于sblocked on。ReentrantLock
Condition
lowPriority
highPriority
highPriority
lowPriority
ReentrantLock
Thread
highPriority
Thread
lowPriority
执行:
public class Main {
public static final Lock lock = new ReentrantLock(true);
public static final Condition lowPriority = lock.newCondition();
public static final Condition highPriority = lock.newCondition();
public static boolean cond;
public static void lowPriority() throws InterruptedException {
try {
lock.lock();
while(!cond) {
lowPriority.await();
}
cond = false;
System.out.println("low");
} finally {
lock.unlock();
}
}
public static void highPriority() throws InterruptedException {
try {
lock.lock();
while(!cond) {
highPriority.await();
}
cond = false;
System.out.println("high");
} finally {
lock.unlock();
}
}
public static void setCond(){
try{
lock.lock();
cond = true;
highPriority.signalAll();
lowPriority.signalAll();
} finally {
lock.unlock();
}
}
}
问题:让我对解决方案感到困惑的问题是,我无法从 JMM 的角度正式证明,只要有Thread
s 被阻止,highPriority
他们总是会赢得Thread
s 被阻止lowPriority
。
当然,我进行了一些实验,高优先级的线程总是获胜,但它在形式上是正确的吗?
解决方案
据我了解,对于代码
highPriority.signalAll();
lowPriority.signalAll();
不能保证某个等待的线程highPriority
会在任何等待的线程之前唤醒lowPriority
。
即使fairness==true
线程可以按随机顺序唤醒1:
但是请注意,锁的公平性并不能保证线程调度的公平性。因此,使用公平锁的许多线程之一可能会连续多次获得它,而其他活动线程没有进展并且当前没有持有锁。
此外,lowPriority.signalAll()
即使一个新的高优先级线程出现在该进程的中间,它也会继续唤醒所有低优先级线程。
所以我会在附加逻辑的开头插入lowPriority
,它检查是否有任何等待的高优先级线程,如果有,让它们先运行。
像这样的东西:
public final class Main {
private final Lock lock = new ReentrantLock();
private final Condition lowPriority = lock.newCondition();
private final Condition highPriority = lock.newCondition();
private int numWaitingHighPriority = 0;
private boolean cond;
public void lowPriority() throws InterruptedException {
lock.lock();
try {
while (!cond || (numWaitingHighPriority > 0)) {
if (numWaitingHighPriority > 0) {
highPriority.signal();
}
lowPriority.await();
}
cond = false;
System.out.println("low");
} finally {
lock.unlock();
}
}
public void highPriority() throws InterruptedException {
lock.lock();
try {
numWaitingHighPriority++;
try {
while (!cond) {
highPriority.await();
}
} finally {
numWaitingHighPriority--;
}
cond = false;
System.out.println("high");
} finally {
lock.unlock();
}
}
public void setCond() {
lock.lock();
try {
cond = true;
((numWaitingHighPriority > 0) ? highPriority : lowPriority).signal();
} finally {
lock.unlock();
}
}
}
推荐阅读
- unity3d - How do you reference an array item within nativeArrray
in ECS - node.js - [GCP][Node] serve [Expressjs] app via HTTPS from GCP Compute Instance
- typescript - `direct-vuex` getters has `{}` type with no property but it's filled at runtime
- wordpress - Wordpress plugin menu issue
- javascript - 如何使用动态源将 Auth Header 添加到 HTML5 视频
- bash - Git-Bash *提示自己*慢
- python - 循环遍历具有多个数组 Python3 的 Json 对象
- go - 我可以将 golang 应用程序作为后台进程运行吗?(没有 nohup)
- mysql - 为什么我的电子应用程序的 mysql 连接查询有延迟?
- monaco-editor - Monaco Editor 对突出显示选定单词的限制