36 import static java.util.concurrent.TimeUnit.MILLISECONDS; |
36 import static java.util.concurrent.TimeUnit.MILLISECONDS; |
37 |
37 |
38 import java.util.Arrays; |
38 import java.util.Arrays; |
39 import java.util.Collection; |
39 import java.util.Collection; |
40 import java.util.HashSet; |
40 import java.util.HashSet; |
|
41 import java.util.concurrent.Callable; |
41 import java.util.concurrent.CountDownLatch; |
42 import java.util.concurrent.CountDownLatch; |
42 import java.util.concurrent.atomic.AtomicBoolean; |
43 import java.util.concurrent.atomic.AtomicBoolean; |
43 import java.util.concurrent.locks.Condition; |
44 import java.util.concurrent.locks.Condition; |
44 import java.util.concurrent.locks.Lock; |
45 import java.util.concurrent.locks.Lock; |
45 import java.util.concurrent.locks.ReentrantReadWriteLock; |
46 import java.util.concurrent.locks.ReentrantReadWriteLock; |
1705 assertTrue(lock.writeLock().toString().contains("Locked by")); |
1706 assertTrue(lock.writeLock().toString().contains("Locked by")); |
1706 lock.writeLock().unlock(); |
1707 lock.writeLock().unlock(); |
1707 assertTrue(lock.writeLock().toString().contains("Unlocked")); |
1708 assertTrue(lock.writeLock().toString().contains("Unlocked")); |
1708 } |
1709 } |
1709 |
1710 |
|
1711 /** |
|
1712 * ThreadMXBean reports the blockers that we expect. |
|
1713 */ |
|
1714 public void testBlockers() { |
|
1715 if (!testImplementationDetails) return; |
|
1716 final boolean fair = randomBoolean(); |
|
1717 final boolean timedAcquire = randomBoolean(); |
|
1718 final boolean timedAwait = randomBoolean(); |
|
1719 final String syncClassName = fair |
|
1720 ? "ReentrantReadWriteLock$FairSync" |
|
1721 : "ReentrantReadWriteLock$NonfairSync"; |
|
1722 final String conditionClassName |
|
1723 = "AbstractQueuedSynchronizer$ConditionObject"; |
|
1724 final Thread.State expectedAcquireState = timedAcquire |
|
1725 ? Thread.State.TIMED_WAITING |
|
1726 : Thread.State.WAITING; |
|
1727 final Thread.State expectedAwaitState = timedAwait |
|
1728 ? Thread.State.TIMED_WAITING |
|
1729 : Thread.State.WAITING; |
|
1730 final Lock lock = new ReentrantReadWriteLock(fair).writeLock(); |
|
1731 final Condition condition = lock.newCondition(); |
|
1732 final AtomicBoolean conditionSatisfied = new AtomicBoolean(false); |
|
1733 lock.lock(); |
|
1734 final Thread thread = newStartedThread((Action) () -> { |
|
1735 if (timedAcquire) |
|
1736 lock.tryLock(LONGER_DELAY_MS, MILLISECONDS); |
|
1737 else |
|
1738 lock.lock(); |
|
1739 while (!conditionSatisfied.get()) |
|
1740 if (timedAwait) |
|
1741 condition.await(LONGER_DELAY_MS, MILLISECONDS); |
|
1742 else |
|
1743 condition.await(); |
|
1744 }); |
|
1745 Callable<Boolean> waitingForLock = () -> { |
|
1746 String className; |
|
1747 return thread.getState() == expectedAcquireState |
|
1748 && (className = blockerClassName(thread)) != null |
|
1749 && className.endsWith(syncClassName); |
|
1750 }; |
|
1751 waitForThreadToEnterWaitState(thread, waitingForLock); |
|
1752 |
|
1753 lock.unlock(); |
|
1754 Callable<Boolean> waitingForCondition = () -> { |
|
1755 String className; |
|
1756 return thread.getState() == expectedAwaitState |
|
1757 && (className = blockerClassName(thread)) != null |
|
1758 && className.endsWith(conditionClassName); |
|
1759 }; |
|
1760 waitForThreadToEnterWaitState(thread, waitingForCondition); |
|
1761 |
|
1762 // politely release the waiter |
|
1763 conditionSatisfied.set(true); |
|
1764 lock.lock(); |
|
1765 try { |
|
1766 condition.signal(); |
|
1767 } finally { lock.unlock(); } |
|
1768 |
|
1769 awaitTermination(thread); |
|
1770 } |
1710 } |
1771 } |