简体   繁体   中英

take() and put() implementation in BlockingQueue

I understand the theory and the concept of BlockingQueue, but when I look at the implementation for LinkedBlockingQueue. I don't get why we use a while loop keep trying and wait in line 8 in the take() method (same for put() ). I thought an if check would be suffice since the signalNotEmpty() which is being called from put() only signal one in line 27 but not all, so only one waiting thread will be woken up, right ? I am wondering do I miss anything ? Can someone explain why we use while instead of if

Here's the code fragment

 1 public E take() throws InterruptedException {
 2      E x;
 3      int c = -1;
 4      final AtomicInteger count = this.count;
 5      final ReentrantLock takeLock = this.takeLock;
 6      takeLock.lockInterruptibly();
 7      try {
 8          while (count.get() == 0) {
 9               notEmpty.await();
10          }
11          x = dequeue();
12          c = count.getAndDecrement();
13          if (c > 1)
14             notEmpty.signal();
15      } finally {
16          takeLock.unlock();
17      }
18      if (c == capacity)
19          signalNotFull();
20      return x;
21 }
22
23 private void signalNotEmpty() {
24     final ReentrantLock takeLock = this.takeLock;
25     takeLock.lock();
26     try {
27         notEmpty.signal();
28     } finally {
29         takeLock.unlock();
30     }
31 }

and what happen if we change line 8 to

if(count.get() == 0) { 
     notEmpty.await();
}

Its because of spurious wakeups . Please read the javadoc of Condition Class also see Do spurious wakeups actually happen?

* <h3>Implementation Considerations</h3>
 *
 * <p>When waiting upon a {@code Condition}, a &quot;<em>spurious
 * wakeup</em>&quot; is permitted to occur, in
 * general, as a concession to the underlying platform semantics.
 * This has little practical impact on most application programs as a
 * {@code Condition} should always be waited upon in a loop, testing
 * the state predicate that is being waited for.  An implementation is
 * free to remove the possibility of spurious wakeups but it is
 * recommended that applications programmers always assume that they can
 * occur and so always wait in a loop.

这是为了赶上竞争状况,如果有多个线程正在等待并且都醒了,那么其他一些线程可能已经进行了信号量计数,因此每个线程都需要再次检查。

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM