user595234
user595234

Reputation: 6259

Why does ArrayBlockingQueue signal 'not full' after catching InterruptedException?

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

Answers (1)

afsantos
afsantos

Reputation: 5208

Imagine the following scenario:

  • Threads 1 and 4 are waiting on notFull, ie, the queue is full, and the lock is released.
  • Thread 2 holds the lock, and is about to remove an element from the queue.
  • Thread 3 interrupts Thread 1.

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

Related Questions