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

时间:2017-10-16 12:34:26

标签: java concurrency synchronization pthreads monitor

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

The order is reversed in pthread。那为什么会有区别呢?感谢。

来自多处理器编程的艺术,

1 class LockedQueue<T> {
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 }

1 个答案:

答案 0 :(得分:-1)

编辑:条件可以视为Object的包装器。但它更多,因为它与锁相连。但是在Object中,有两种方法,wait()(await())用于工作,而notifyAll()(signal())工作完成。看看这个堆栈答案Why should the notify method be inside a synchronized block?

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

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

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

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