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();
}