Reputation: 6259
In ArrayBlockingQueue
, inside the put
method, why does it call notFull.signal()
after catching InterruptedException
? When the thread is going to terminate, why does it send out a 'not full' signal?
From the source:
public void put(E e) throws InterruptedException {
if (e == null) throw new NullPointerException();
final E[] items = this.items;
final ReentrantLock lock = this.lock;
lock.lockInterruptibly();
try {
try {
while (count == items.length)
notFull.await();
} catch (InterruptedException ie) {
notFull.signal(); // propagate to non-interrupted thread
throw ie;
}
insert(e);
} finally {
lock.unlock();
}
}
Upvotes: 1
Views: 99
Reputation: 5208
Imagine the following scenario:
notFull
, ie, the queue is full, and the lock is released.Now imagine the following interleaving:
+-+--+--------+-----------+------- TIME +---+------------+---------------------->
| | | | | | | |
+---------+ +------------------+ +----------+ |
| Thread2 | | Thread2 | | Thread2 | |
| lock() | | notFull.signal() | | unlock() | |
+---------+ +------------------+ +----------+ |
| | | | |
+---------------------+ | | |
| Thread3 | | | |
| Thread1.interrupt() | | | |
+---------------------+ | | |
| | | |
+---------------+ +-------------+ +---------+ +----------------------+
| Thread1 | | Thread1 | | Thread1 | | Thread1 |
| interrupted() | | signalled() | | lock() | | InterruptedException |
+---------------+ +-------------+ +---------+ +----------------------+
What if InterruptedException
wasn't caught, and Thread 1 was just to unlock and abandon the wait? What would happen to Thread 4, who was still waiting for a signal on notFull
? The signal had already been sent by Thread 2, but it just so happened that the receiving thread, Thread 1, had been interrupted, and the signal was wasted.
In short: If the thread received a signal when it was also interrupted, it passes along the signal to another thread, so that it isn't lost. This prevents threads from waiting indefinitely for something that already happened.
Upvotes: 1