据我了解,关键部分 #2 必须以与关键部分 #1 相同的顺序执行
如果线程 T1 在线程 T2 之前执行 block1,那么 T1 应该在 T2 之前执行 block2。有两个以上的线程。
然后可以使用队列来确保执行顺序。
private Object lock = new Object();
private Queue<Thread> threadQueue = new ArrayDeque<>();
// https://stackoverflow.com/questions/32353283/synchronization-threads-execute-two-critical-sections-in-same-order
public void executeCriticalSectionsInOrder() throws InterruptedException {
// Critical Section #1
synchronized (lock){
// synchronized code #1
// Add self to queue
threadQueue.add(Thread.currentThread());
}
// {lot of code where synchronization not necessary}
// Critical Section #2
synchronized (lock) {
//All the threads that executed block1 before this thread should have already executed this block.
// Wait turn
Thread t = threadQueue.element(); // Do not remove until it is self
while (t != Thread.currentThread()) {
lock.wait();
// After sleep try again
t = threadQueue.element();
}
// Verified own turn. Update status
threadQueue.remove();
// synchronized code #2
lock.notifyAll(); // Awake any waiting thread after exiting section.
}
但是,如果一个线程死亡/退出而没有将自己从队列中移除,那么后续线程将被无限期地阻塞。也许添加一个 finally 块来做家务?
注意:在Nicholas Robinson 的回答中,建议使用位置顺序而不是队列,这似乎更有效。