【发布时间】:2021-08-27 19:34:02
【问题描述】:
问题:我有一组Threads,其中一些必须优先于其他获得ReentrantLock。
解决方案:我可以想象有一个 公平 ReentrantLock 和 2 个 Condition 队列:lowPriority 和 highPriority。重点是highPriority 在lowPriority 之前发出信号。考虑到ReentrantLock 的公平性,Threads 在highPriority 中被阻止总是在Threads 在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 的角度正式证明,一旦 Threads 被阻止在 @ 987654336@ 他们总是赢 Threads 被 lowPriority 屏蔽。
当然,我进行了一些实验,高优先级的线程总是获胜,但形式上正确吗?
【问题讨论】:
-
我认为,这只是由
ReentrantLock实现管理,而不是 JMM。但是,当您尝试从 JMM 的角度进行推理时,分享您迄今为止的想法会很有帮助。 -
@Holger 我最困惑的是当
signalAll返回时,假设所有Threads 等待给定Condifition已经在ReentrantLock中排队是可靠的吗? sWaitSet? -
我验证了当前实现确实将所有线程转移到等待队列中,并且在启用公平性时,发出信号的线程检查它们是否是队列中的第一个。但是,我不确定我们是否假设实现必须按照规范的措辞那样做。
-
也许您可以使用
PriorityQueue来保存带有Condition的对象。仅当线程需要等待时,才将项目添加到队列中。任务完成后,您轮询队列并向其他人发出信号。 -
@Holger 我重新思考了这个想法,发现了以下竞争条件:
Thread 1表示所有在Condition highPriority上阻塞的高优先级线程。Thread 2到达中间并调用setCond()为highPriority和lowPriority线程带来重要更新。出于公平考虑,Thread 2在所有highPriority线程之后都在ReentrantLock上排队。然后在lowPriority上阻塞的所有线程都由Thread 1发出信号,并在Thread 2.Thread 2再次发出高优先级和低优先级线程信号之后调度,高优先级线程丢失更新
标签: java multithreading concurrency jvm reentrantlock