<div dir="ltr"><div dir="ltr"><div>Hi Kim,</div><div><br></div><div>I think there may be an issue with your test. Specifically, this code is suspect:</div><div><pre> // Wait for the producer thread to enter BLOCKED state
// This ensures that the thread is waiting on the full queue
while (thread.getState() == State.RUNNABLE || thread.getState() == State.NEW);</pre></div><div>I don't think that actually guarantees that the thread is blocked in <span style="font-family:monospace">put()</span>.<br></div><div><br></div><div>I was able to reproduce the bug using <span style="font-family:monospace">ArrayBlockingQueue()</span>, but could no longer reproduce it after I changed the above code to this:</div><div><br></div><div><span style="font-family:monospace"> // Wait for the producer thread to block in queue.put()<br> // This ensures that the thread is waiting on the full queue<br> while (!queue.isPutting(thread));</span><br></div><div><br></div><div>after also making this change to <span style="font-family:monospace">ArrayBlockingQueue.java</span>:</div><div><br></div><div style="margin-left:40px"><span style="font-family:monospace">--- a/src/java.base/share/classes/java/util/concurrent/ArrayBlockingQueue.java<br>+++ b/src/java.base/share/classes/java/util/concurrent/ArrayBlockingQueue.java<br>@@ -365,10 +365,31 @@ public void put(E e) throws InterruptedException {<br> Objects.requireNonNull(e);<br> final ReentrantLock lock = this.lock;<br> lock.lockInterruptibly();<br>+ final boolean added = puttingThreads.add(Thread.currentThread());<br> try {<br> while (count == items.length)<br> notFull.await();<br> enqueue(e);<br>+ } finally {<br>+ if (added)<br>+ puttingThreads.remove(Thread.currentThread());<br>+ lock.unlock();<br>+ }<br>+ }<br>+<br>+ private final java.util.HashSet<Thread> puttingThreads = new java.util.HashSet<>();<br>+<br>+ /**<br>+ * Test for putting thread.<br>+ *<br>+ * @param thread thread to test<br>+ * @return true if thread is a putting thread<br>+ */<br>+ public boolean isPutting(Thread thread) {<br>+ final ReentrantLock lock = this.lock;<br>+ lock.lock();<br>+ try {<br>+ return puttingThreads.contains(thread);<br> } finally {<br> lock.unlock();<br> }</span></div><div><br></div><div>So the original test may not be correct due to Java memory model subtleties, etc.<br></div><div><br></div><div>-Archie<br></div><br></div><span class="gmail_signature_prefix">-- </span><br><div dir="ltr" class="gmail_signature">Archie L. Cobbs<br></div></div>