ReentrantLock 条件的优先级

Prioritization on ReentrantLock's Condition

问题: 我有一组 Thread,其中一些必须优先于其他获取 ReentrantLock

解决办法:我可以想象有一个公平 ReentrantLock 有 2 个 Condition 队列:lowPriorityhighPriority。重点是 highPrioritylowPriority 之前发出信号。考虑到 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 的角度正式证明一旦出现ThreadhighPriority 上被屏蔽,他们总是赢 ThreadlowPriority 上被屏蔽。

当然我 运行 一些实验和高优先级线程总是赢,但它在形式上是正确的吗?

据我了解,对于代码

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();
    }
  }
}