It is possible that a thread waiting on await will be signaled and interrupted, and that interruption will take precedence. The following code demonstrates this:
import java.util.concurrent.locks.Condition; import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.ReentrantLock; public class SignalTest { public static void main(String... args) throws InterruptedException { for ( int i = 0; i < 2000; i++ ) { tryOnce(); } } private static void tryOnce() throws InterruptedException { final Lock lock = new ReentrantLock(); final Condition condition = lock.newCondition(); Thread t = new Thread(new Runnable() { public void run() { try { lock.lockInterruptibly(); condition.await(); } catch (InterruptedException e) { e.printStackTrace(); } finally { lock.unlock(); } } }); t.start(); Thread.sleep(1); lock.lock(); condition.signal(); t.interrupt(); lock.unlock(); } }
For me, 2-10 attempts of 2000 lead to an InterruptedException , although I signal before I interrupt and do both from the same thread.
Since this is a very real possibility, if the catch block did not throttle the signal , this can lead to a wait state, even if space is available for adding a new element. Thus, instead, the condition is signaled, and if there is another waiting thread, it wakes up.
This is safe, because after waking up, the code should always make sure that the condition in which they were woken up (that the queue was not filled) is really true (in this case, if (count != items.length)... ). The code does not assume that from the moment it wakes up, the condition must be true.
Edit
In addition, to help your understanding, it is important to note that the for loop is not strictly mutually exclusive. If two threads require a simultaneous offer, the second will wait until the first gives a lock , this is true, but you should understand that calling notFull.await() releases the lock (the lock will be raised again after await() returns). This way you can block multiple threads when await() offer() called, rather than just lock in lockInterruptably() .
Since this is the case (at the same time, several await() locks occur), if the intermittent stream silently ignores the signal, then none of the other threads will be awakened in its place.