我在“实践中的Java并发”中找到了这个
一个重要的三方关系 条件等待涉及锁定,等待方法和 条件谓词。条件谓词涉及 状态变量,状态变量受到保护 通过锁定,所以在测试条件之前 谓词,我们必须持有那个锁。 锁定对象 和条件队列对象(在其上的对象) 等待和通知被调用)也必须是相同的 对象
这是示例代码:
abstract class BaseBoundedBuffer<V> {
private final V[] buf;
private int tail;
private int head;
private int count;
protected BaseBoundedBuffer(int capacity) {
this.buf = (V[]) new Object[capacity];
}
protected synchronized final void doPut(V v) {
buf[tail] = v;
if (++tail == buf.length)
tail = 0;
++count; }
protected synchronized final V doTake() {
V v = buf[head];
buf[head] = null;
if (++head == buf.length)
head = 0;
--count;
return v; }
public synchronized final boolean isFull() {
return count == buf.length;
}
public synchronized final boolean isEmpty() {
return count == 0;
}
}
public class BoundedBuffer<V> extends BaseBoundedBuffer<V> {
// CONDITION PREDICATE: not-full (!isFull())
// CONDITION PREDICATE: not-empty (!isEmpty())
public BoundedBuffer(int size) { super(size); }
// BLOCKS-UNTIL: not-full
public synchronized void put(V v) throws InterruptedException {
while (isFull())
wait();
doPut(v);
notifyAll();
}
// BLOCKS-UNTIL: not-empty
public synchronized V take() throws InterruptedException {
while (isEmpty())
wait();
V v = doTake();
notifyAll();
return v;
}
}
锁定对象和条件队列对象都是this
。
如果我以这种方式编写代码:
public class BoundedBuffer<V> extends BaseBoundedBuffer<V> {
// CONDITION PREDICATE: not-full (!isFull())
// CONDITION PREDICATE: not-empty (!isEmpty())
private Object conditionQueue = new Object();
public BoundedBuffer(int size) { super(size); }
// BLOCKS-UNTIL: not-full
public synchronized void put(V v) throws InterruptedException {
while (isFull())
conditionQueue.wait();
doPut(v);
conditionQueue.notifyAll();
}
// BLOCKS-UNTIL: not-empty
public synchronized V take() throws InterruptedException {
while (isEmpty())
conditionQueue.wait();
V v = doTake();
conditionQueue.notifyAll();
return v;
}
}
锁定对象为this
,条件队列对象为conditionQueue
。
锁对象与条件队列对象不同,我不知道为什么这种方式不好。
所以任何人都可以告诉我为什么锁对象和条件队列对象必须是同一个对象?
答案 0 :(得分:1)
自我回答。
我明白为什么锁对象和条件队列对象必须是同一个对象。
condtionQueue.wait()
仅释放由conditionQueue
守卫的锁定。但是在这种情况下,我们除了线程等待时,线程应该释放由this
保护的锁。
因此锁对象和条件队列对象必须是同一个对象。因此,当线程等待时,锁定对象所锁定的锁将被释放。