【问题标题】:Blocking queue in JavaJava中的阻塞队列
【发布时间】:2013-04-20 22:33:56
【问题描述】:

我正在阅读一本名为“Beginning Algorithms”的书,其中包含 Java 示例。在关于队列的章节中,它解释了“阻塞队列”,并且......即使我的背景是 C# 而不是 Java,我觉得有些东西很有趣。

这是代码的一部分(我省略了不相关的部分):

public void enqueue(Object value){
    synchronized(_mutex){
        while(size == _max_size){
            waitForNotification();
        }
        _queue.enqueue(value);
        _mutex.notifyAll();
    }
}

private void waitForNotification(){
    try {
        _mutex.wait();
    } catch( InterruptedException e){
        // Ignore
    }
}

public Object dequeue() throws EmptyQueueException {
    synchronized(_mutex){
        while(isEmpty()){
            waitForNotification();
        }
        Object value = _queue.dequeue();
        _mutex.notifyAll();
        return value;
    }
}

我看到了两个主要问题。

首先,如果队列满了,有5个线程在等待添加item,其他线程dequeue 1 item,另外5个会被释放,同时会检查“size() == _max_size”是否不再为真,他们将尝试调用“_queue.enqueue”5 次,导致队列溢出。

其次,同样的情况也发生在“dequeue”中。如果由于队列为空而阻止多个线程尝试使项目出队,添加一个将导致所有线程检查队列不再为空,并且所有线程都将尝试出队,得到 null 或我猜的异常。

我说的对吗?我的 C# 有一个“Monitor.Pulse”,它只释放一个被阻塞的线程,这会是解决方案吗?

干杯。

【问题讨论】:

  • 即使在 notifyAll() 之后所有五个假设线程都可能被唤醒,但只有一个线程会获取 _mutex 并进入同步块。其余的将重新进入睡眠状态(编辑:仍在等待进入同步块)
  • 看起来你的(幻数)5 个线程正在使用同一个队列,所以实现是说让其他对象在一个线程添加或删除队列中的元素时等待。
  • 如果 5 个线程在 "_mutex.wait()" 中被阻塞,它们已经在同步块内,如果我调用 "_mutex.notifyAll()",只有一个被唤醒?

标签: java multithreading synchronization synchronized


【解决方案1】:

您忽略了synchronized 声明。这只允许一个线程获取_mutex。因此,只有一个线程能够检查size 的值,因为while 语句位于synchronized 块内。

this thread 中所述,wait() 方法实际上释放了_mutex 对象并等待对notify() 的调用,或者在这种情况下为notifyAll()。此外,notifyAll() 只会将_mutex 上的锁授予一个等待线程。

【讨论】:

  • 我明白了。所以即使一个线程在“.wait()”中被阻塞,同步语句仍然会阻止其他线程进入“while”,对吧?
  • 谢谢。这让我质疑“notify”和“notifyAll”之间的区别,但我已经得到了答案。干杯。
猜你喜欢
  • 1970-01-01
  • 2014-10-16
  • 1970-01-01
  • 2010-11-15
  • 1970-01-01
  • 2010-10-24
  • 2022-11-19
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多