Robin Han
Robin Han

Reputation: 101

Why the lock object and condition queue object must be the same object?

I find this in "Java concurrency in practice"

There is an important threeway relationship in a condition wait involving locking, the wait method, and a condition predicate. The condition predicate involves state variables, and the state variables are guarded by a lock, so before testing the condition predicate, we must hold that lock. The lock object and the condition queue object (the object on which wait and notify are invoked)must also be the same object.

This is the example code:

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;
    } 
}

The lock object and condition queue object both are this.

If I write the code in this way:

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;
    } 
}

The lock object is this and the condition queue object is conditionQueue.

The lock object is different from condition queue object and I don't figure out why this way is not good.

So anyone could tell me why the lock object and condition queue object must be the same object?

Upvotes: 0

Views: 354

Answers (1)

Robin Han
Robin Han

Reputation: 101

Self answer.

I got the point why lock object and condition queue object must be the same object.

condtionQueue.wait() only release the lock guarded by conditionQueue. But in this condition, we except when the thread wait, the thread should release the lock guarded by this.

So the lock object and condition queue object must be the same object. So that when thread wait, the lock guraded by lock object will be released.

Upvotes: 1

Related Questions