为什么在Java中调用信号后调用解锁?

在Java中,为什么在调用signal( notFull.signal()notFull.signal() )之后解锁被调用( notFull.signal() )?

顺序在pthread中反转 。 那么为什么会有区别呢? 谢谢。

从多处理器编程的艺术,

 1 class LockedQueue { 2 final Lock lock = new ReentrantLock(); 3 final Condition notFull = lock.newCondition(); 4 final Condition notEmpty = lock.newCondition(); 5 final T[] items; 6 int tail, head, count; 7 public LockedQueue(int capacity) { 8 items = (T[])new Object[capacity]; 9 } 10 public void enq(T x) { 11 lock.lock(); 12 try { 13 while (count == items.length) 14 notFull.await(); 15 items[tail] = x; 16 if (++tail == items.length) 17 tail = 0; 18 ++count; 19 notEmpty.signal(); 20 } finally { 21 lock.unlock(); 22 } 23 } 24 public T deq() { 25 lock.lock(); 26 try { 27 while (count == 0) 28 notEmpty.await(); 29 T x = items[head]; 30 if (++head == items.length) 31 head = 0; 32 --count; 33 notFull.signal(); 34 return x; 35 } finally { 36 lock.unlock(); 37 } 38 } 39 } 

编辑:条件可以视为对象的包装。 但它更多,因为它与锁相连。 但是在Object中,有两种方法,wait()(await())用于工作,而notifyAll()(signal())工作完成。 看看这个堆栈的答案为什么notify方法应该在synchronized块中呢?

在您提供的代码中,有些情况下,线程无法继续。 如果队列已满,并且您想要添加元素,则无法继续。 您可以在没有await()signals()情况下执行此操作,但是您的代码必须返回失败,或者抛出exception,例如QueueIsFullException

代码的调用者希望有一个简单的界面。 他们想要只放入元素,而不是做while循环并尝试插入元素(忙碌旋转,cpu密集)。 这就是为什么有等待和信号(等到准备好,不消耗CPU)。

因此当thread1卡住等待插入元素的位置(等待第14行)时,它会释放锁定,其他线程可以自由获取它。

当thread2获取该元素时,它向thread1发出信号,该队列未满。 因此,当thread2解锁时,thread1会重新获取锁定。