首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >为什么锁对象和条件队列对象必须是同一个对象?

为什么锁对象和条件队列对象必须是同一个对象?
EN

Stack Overflow用户
提问于 2015-10-21 06:55:09
回答 1查看 352关注 0票数 0

我在“实践中的Java并发性”中发现了这一点。

在条件等待中有一个重要的三方关系,包括锁定、等待方法和条件谓词。条件谓词涉及状态变量,状态变量由锁保护,因此在测试条件谓词之前,我们必须持有该锁。锁对象和条件队列对象(调用等待和通知的对象)也必须是同一个对象。

以下是示例代码:

代码语言:javascript
复制
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

如果我以这种方式编写代码:

代码语言:javascript
复制
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

锁对象不同于条件队列对象,我不明白为什么这种方式不好。

所以任何人都可以告诉我为什么锁对象和条件队列对象必须是同一个对象?

EN

回答 1

Stack Overflow用户

发布于 2015-10-21 07:28:56

自我回答。

我明白了为什么锁对象和条件队列对象必须是同一个对象。

condtionQueue.wait()只释放由conditionQueue保护的锁。但是在这种情况下,除了线程等待时,线程应该释放由this保护的锁。

因此,锁对象和条件队列对象必须是同一个对象。这样,当线程等待时,锁对象所引导的锁将被释放。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/33252811

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档