1

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();
}
peter
  • 8,333
  • 17
  • 71
  • 94

3 Answers3

2

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.
Community
  • 1
  • 1
veritas
  • 2,444
  • 1
  • 21
  • 30
1

Reason for this is "spurious wakeup". See: http://docs.oracle.com/javase/7/docs/api/java/lang/Object.html#wait()

ilj
  • 859
  • 8
  • 18
-1

This is to catch a race condition, if multiple threads were waiting and they all woke up, some other thread may have already taken semaphore count, so each thread needs to check again.