Upstream v12 replaces notify() with notifyAll() on successful queue operations.

What Changed

Instead of notifying one thread, successful Put and Get operations notify all waiting threads. The independent notification step from the previous attempted fix is removed.

Waking the Wrong Kind of Thread

With notify(), the JVM might wake up a thread that cannot make progress (e.g., waking a producer when the buffer is already full). That thread goes back to waiting, and the actual thread that could make progress is never woken - leading to deadlock.

The Fix

notifyAll() makes all waiters eligible to reacquire the shared lock and recheck their conditions. This fixes the modeled deadlock, but waking threads that cannot proceed can add contention. It does not by itself guarantee fair scheduling or freedom from starvation.

As a bonus exercise, check if it is necessary to notify all waiting threads in both Put and Get.

The upstream tutorial notes that using notifyAll() in just one of the two operations suffices for this deadlock fix. Try keeping NotifyAll in one operation and restoring the earlier single-thread Notify in the other. The next lesson avoids waking the wrong kind of thread in the first place.

Expected Result

TLC completes without a deadlock or invariant violation for the supplied p4c3b3 model. This is a finite-model result, not a proof for every configuration or a liveness guarantee.


Based on the BlockingQueue repository by Markus Kuppe, licensed under MIT. · View commit on GitHub