Java BlockingQueue 混淆

huangapple go评论71阅读模式
英文:

Java BlockingQueue confusion

问题

我正在阅读关于Java BlockingQueue 的内容,许多网站上都提供了一个简单的BlockingQueue实现的示例。代码很简单,但我有点困惑。例如,假设我们填满了队列,然后尝试再次入队3次。这将使3个线程等待。然后当我们调用dequeue时,dequeue方法中的代码将进入第二个if语句,并且会通知所有线程。这是否意味着等待的3个线程都会将节点添加到队列中?这意味着我们将比限制多2个节点吗?我相当确定我在这里误解了一些东西,所以我需要一些简要的解释。

英文:

I am currently reading about Java BlockingQueue and this example is given on many websites for a simple implementation of the BlockingQueue. The code is simple but I am a bit confused. For example lets say we fill up the queue, then we try to enqueue 3 more times. This will make the 3 threads wait. Then when we call dequeue, the code in the dequeue method will enter the second if statement and it will notify all threads. Won't this mean that the 3 threads waiting will all add nodes to the queue? That means we will have 2 more nodes than the limit? I am pretty sure I misunderstood something here so I could use some small explanation.

public class BlockingQueue {

  private List queue = new LinkedList();
  private int  limit = 10;

  public BlockingQueue(int limit){
    this.limit = limit;
  }


  public synchronized void enqueue(Object item)
  throws InterruptedException  {
    while(this.queue.size() == this.limit) {
      wait();
    }
    this.queue.add(item);
    if(this.queue.size() == 1) {
      notifyAll();
    }
  }


  public synchronized Object dequeue()
  throws InterruptedException{
    while(this.queue.size() == 0){
      wait();
    }
    if(this.queue.size() == this.limit){
      notifyAll();
    }

    return this.queue.remove(0);
  }

}

答案1

得分: 1

No, only one will add a node. Notice that your wait-call in enqueue is inside a loop:

    while(this.queue.size() == this.limit) {
      wait();
    }

All three threads are notified but only one thread can be in the synchronized-block. The first thread to enter the block adds a node, so the queue is full again. The other both threads enter the block (one after another) but see the queue being full again, which will put them right into waiting state again as that's the loop-condition.

You can imagine a wait to be an exit and entrance point of a synchronized-block. When a thread enters wait, then the corresponding lock is released. A thread that has been waiting in a wait and is notified, is trying to acquire the corresponding lock for the critical section again and blocks if it is currently in use. So only one of the notified three threads can enter at a time.

英文:

No, only one will add a node. Notice that your wait-call in enqueue is inside a loop:

    while(this.queue.size() == this.limit) {
      wait();
    }

All three threads are notified but only one thread can be in the synchronized-block. The first thread to enter the block adds a node, so the queue is full again. The other both threads enter the block (one after another) but see the queue being full again, which will put them right into waiting state again as that's the loop-condition.

You can imagine a wait to be an exit and entrace point of a synchronized-block. When a thread enters wait, then the corresponding lock is released. A thread that has been waiting in a wait and is notified, is trying to acquire the corresponding lock for the critical section again and blocks if it is currently in use. So only one of the notified three threads can enter at a time.

答案2

得分: 1

请注意,来自.enqueue()wait()位于循环内部。任何被唤醒的线程都将重新检查许可以添加元素,由于一次只有一个线程可以执行同步方法,所以不会有问题 - 一个线程有幸插入一个元素,其他线程在失败的重新检查后继续等待。

英文:

Note that wait() from .enqueue() is inside loop. Any awoken thread will re-check permit to add an element and since only single thread can execute synchronized method at a time, there will be no problem - one thread gets lucky to insert an element, others continue to wait after failed re-check.

huangapple
  • 本文由 发表于 2020年8月7日 17:56:09
  • 转载请务必保留本文链接:https://go.coder-hub.com/63299412.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定