11 |
|
import java.util.Arrays; |
12 |
|
import java.util.Collection; |
13 |
|
import java.util.HashSet; |
14 |
+ |
import java.util.concurrent.Callable; |
15 |
|
import java.util.concurrent.CountDownLatch; |
16 |
|
import java.util.concurrent.atomic.AtomicBoolean; |
17 |
|
import java.util.concurrent.locks.Condition; |
1681 |
|
assertTrue(lock.writeLock().toString().contains("Unlocked")); |
1682 |
|
} |
1683 |
|
|
1684 |
+ |
/** |
1685 |
+ |
* ThreadMXBean reports the blockers that we expect. |
1686 |
+ |
*/ |
1687 |
+ |
public void testBlockers() { |
1688 |
+ |
if (!testImplementationDetails) return; |
1689 |
+ |
final boolean fair = randomBoolean(); |
1690 |
+ |
final boolean timedAcquire = randomBoolean(); |
1691 |
+ |
final boolean timedAwait = randomBoolean(); |
1692 |
+ |
final String syncClassName = fair |
1693 |
+ |
? "ReentrantReadWriteLock$FairSync" |
1694 |
+ |
: "ReentrantReadWriteLock$NonfairSync"; |
1695 |
+ |
final String conditionClassName |
1696 |
+ |
= "AbstractQueuedSynchronizer$ConditionObject"; |
1697 |
+ |
final Thread.State expectedAcquireState = timedAcquire |
1698 |
+ |
? Thread.State.TIMED_WAITING |
1699 |
+ |
: Thread.State.WAITING; |
1700 |
+ |
final Thread.State expectedAwaitState = timedAwait |
1701 |
+ |
? Thread.State.TIMED_WAITING |
1702 |
+ |
: Thread.State.WAITING; |
1703 |
+ |
final Lock lock = new ReentrantReadWriteLock(fair).writeLock(); |
1704 |
+ |
final Condition condition = lock.newCondition(); |
1705 |
+ |
final AtomicBoolean conditionSatisfied = new AtomicBoolean(false); |
1706 |
+ |
lock.lock(); |
1707 |
+ |
final Thread thread = newStartedThread((Action) () -> { |
1708 |
+ |
if (timedAcquire) |
1709 |
+ |
lock.tryLock(LONGER_DELAY_MS, MILLISECONDS); |
1710 |
+ |
else |
1711 |
+ |
lock.lock(); |
1712 |
+ |
while (!conditionSatisfied.get()) |
1713 |
+ |
if (timedAwait) |
1714 |
+ |
condition.await(LONGER_DELAY_MS, MILLISECONDS); |
1715 |
+ |
else |
1716 |
+ |
condition.await(); |
1717 |
+ |
}); |
1718 |
+ |
Callable<Boolean> waitingForLock = () -> { |
1719 |
+ |
String className; |
1720 |
+ |
return thread.getState() == expectedAcquireState |
1721 |
+ |
&& (className = blockerClassName(thread)) != null |
1722 |
+ |
&& className.endsWith(syncClassName); |
1723 |
+ |
}; |
1724 |
+ |
waitForThreadToEnterWaitState(thread, waitingForLock); |
1725 |
+ |
|
1726 |
+ |
lock.unlock(); |
1727 |
+ |
Callable<Boolean> waitingForCondition = () -> { |
1728 |
+ |
String className; |
1729 |
+ |
return thread.getState() == expectedAwaitState |
1730 |
+ |
&& (className = blockerClassName(thread)) != null |
1731 |
+ |
&& className.endsWith(conditionClassName); |
1732 |
+ |
}; |
1733 |
+ |
waitForThreadToEnterWaitState(thread, waitingForCondition); |
1734 |
+ |
|
1735 |
+ |
// politely release the waiter |
1736 |
+ |
conditionSatisfied.set(true); |
1737 |
+ |
lock.lock(); |
1738 |
+ |
try { |
1739 |
+ |
condition.signal(); |
1740 |
+ |
} finally { lock.unlock(); } |
1741 |
+ |
|
1742 |
+ |
awaitTermination(thread); |
1743 |
+ |
} |
1744 |
|
} |