在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 }
答案 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会重新获取锁定。