我在“实践中的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。
锁对象不同于条件队列对象,我不明白为什么这种方式不好。
所以任何人都可以告诉我为什么锁对象和条件队列对象必须是同一个对象?
发布于 2015-10-21 07:28:56
自我回答。
我明白了为什么锁对象和条件队列对象必须是同一个对象。
condtionQueue.wait()只释放由conditionQueue保护的锁。但是在这种情况下,除了线程等待时,线程应该释放由this保护的锁。
因此,锁对象和条件队列对象必须是同一个对象。这样,当线程等待时,锁对象所引导的锁将被释放。
https://stackoverflow.com/questions/33252811
复制相似问题