ReentrantLock 条件的优先级
Prioritization on ReentrantLock's Condition
问题: 我有一组 Thread
,其中一些必须优先于其他获取 ReentrantLock
。
解决办法:我可以想象有一个公平 ReentrantLock
有 2 个 Condition
队列:lowPriority
和 highPriority
。重点是 highPriority
在 lowPriority
之前发出信号。考虑到 ReentrantLock
的公平性,在 highPriority
中被阻止的 Thread
总是先于 lowPriority
中被阻止的 Thread
。
执行:
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
在 highPriority
上被屏蔽,他们总是赢 Thread
在 lowPriority
上被屏蔽。
当然我 运行 一些实验和高优先级线程总是赢,但它在形式上是正确的吗?
据我了解,对于代码
highPriority.signalAll();
lowPriority.signalAll();
无法保证某些等待 highPriority
的线程会在任何等待 lowPriority
的线程之前唤醒。
即使 fairness==true
线程可以随机顺序唤醒 1:
Note however, that fairness of locks does not guarantee fairness of thread scheduling. Thus, one of many threads using a fair lock may obtain it multiple times in succession while other active threads are not progressing and not currently holding the lock.
此外,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();
}
}
}
问题: 我有一组 Thread
,其中一些必须优先于其他获取 ReentrantLock
。
解决办法:我可以想象有一个公平 ReentrantLock
有 2 个 Condition
队列:lowPriority
和 highPriority
。重点是 highPriority
在 lowPriority
之前发出信号。考虑到 ReentrantLock
的公平性,在 highPriority
中被阻止的 Thread
总是先于 lowPriority
中被阻止的 Thread
。
执行:
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
在 highPriority
上被屏蔽,他们总是赢 Thread
在 lowPriority
上被屏蔽。
当然我 运行 一些实验和高优先级线程总是赢,但它在形式上是正确的吗?
据我了解,对于代码
highPriority.signalAll();
lowPriority.signalAll();
无法保证某些等待 highPriority
的线程会在任何等待 lowPriority
的线程之前唤醒。
即使 fairness==true
线程可以随机顺序唤醒 1:
Note however, that fairness of locks does not guarantee fairness of thread scheduling. Thus, one of many threads using a fair lock may obtain it multiple times in succession while other active threads are not progressing and not currently holding the lock.
此外,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();
}
}
}