test/jdk/java/util/concurrent/tck/ReentrantReadWriteLockTest.java
changeset 58385 489532b89775
parent 48843 21efc1774302
--- a/test/jdk/java/util/concurrent/tck/ReentrantReadWriteLockTest.java	Fri Sep 27 10:48:23 2019 -0700
+++ b/test/jdk/java/util/concurrent/tck/ReentrantReadWriteLockTest.java	Fri Sep 27 12:20:14 2019 -0700
@@ -38,6 +38,7 @@
 import java.util.Arrays;
 import java.util.Collection;
 import java.util.HashSet;
+import java.util.concurrent.Callable;
 import java.util.concurrent.CountDownLatch;
 import java.util.concurrent.atomic.AtomicBoolean;
 import java.util.concurrent.locks.Condition;
@@ -1707,4 +1708,64 @@
         assertTrue(lock.writeLock().toString().contains("Unlocked"));
     }
 
+    /**
+     * ThreadMXBean reports the blockers that we expect.
+     */
+    public void testBlockers() {
+        if (!testImplementationDetails) return;
+        final boolean fair = randomBoolean();
+        final boolean timedAcquire = randomBoolean();
+        final boolean timedAwait = randomBoolean();
+        final String syncClassName = fair
+            ? "ReentrantReadWriteLock$FairSync"
+            : "ReentrantReadWriteLock$NonfairSync";
+        final String conditionClassName
+            = "AbstractQueuedSynchronizer$ConditionObject";
+        final Thread.State expectedAcquireState = timedAcquire
+            ? Thread.State.TIMED_WAITING
+            : Thread.State.WAITING;
+        final Thread.State expectedAwaitState = timedAwait
+            ? Thread.State.TIMED_WAITING
+            : Thread.State.WAITING;
+        final Lock lock = new ReentrantReadWriteLock(fair).writeLock();
+        final Condition condition = lock.newCondition();
+        final AtomicBoolean conditionSatisfied = new AtomicBoolean(false);
+        lock.lock();
+        final Thread thread = newStartedThread((Action) () -> {
+            if (timedAcquire)
+                lock.tryLock(LONGER_DELAY_MS, MILLISECONDS);
+            else
+                lock.lock();
+            while (!conditionSatisfied.get())
+                if (timedAwait)
+                    condition.await(LONGER_DELAY_MS, MILLISECONDS);
+                else
+                    condition.await();
+        });
+        Callable<Boolean> waitingForLock = () -> {
+            String className;
+            return thread.getState() == expectedAcquireState
+            && (className = blockerClassName(thread)) != null
+            && className.endsWith(syncClassName);
+        };
+        waitForThreadToEnterWaitState(thread, waitingForLock);
+
+        lock.unlock();
+        Callable<Boolean> waitingForCondition = () -> {
+            String className;
+            return thread.getState() == expectedAwaitState
+            && (className = blockerClassName(thread)) != null
+            && className.endsWith(conditionClassName);
+        };
+        waitForThreadToEnterWaitState(thread, waitingForCondition);
+
+        // politely release the waiter
+        conditionSatisfied.set(true);
+        lock.lock();
+        try {
+            condition.signal();
+        } finally { lock.unlock(); }
+
+        awaitTermination(thread);
+    }
 }