37 |
37 |
38 import java.util.ArrayList; |
38 import java.util.ArrayList; |
39 import java.util.Arrays; |
39 import java.util.Arrays; |
40 import java.util.Collection; |
40 import java.util.Collection; |
41 import java.util.HashSet; |
41 import java.util.HashSet; |
|
42 import java.util.concurrent.Callable; |
42 import java.util.concurrent.CountDownLatch; |
43 import java.util.concurrent.CountDownLatch; |
43 import java.util.concurrent.CyclicBarrier; |
44 import java.util.concurrent.CyclicBarrier; |
44 import java.util.concurrent.ThreadLocalRandom; |
45 import java.util.concurrent.ThreadLocalRandom; |
|
46 import java.util.concurrent.atomic.AtomicBoolean; |
45 import java.util.concurrent.locks.Condition; |
47 import java.util.concurrent.locks.Condition; |
|
48 import java.util.concurrent.locks.Lock; |
46 import java.util.concurrent.locks.ReentrantLock; |
49 import java.util.concurrent.locks.ReentrantLock; |
47 |
50 |
48 import junit.framework.Test; |
51 import junit.framework.Test; |
49 import junit.framework.TestSuite; |
52 import junit.framework.TestSuite; |
50 |
53 |
1220 for (Thread thread : threads) { |
1223 for (Thread thread : threads) { |
1221 thread.join(LONG_DELAY_MS); |
1224 thread.join(LONG_DELAY_MS); |
1222 assertFalse(thread.isAlive()); |
1225 assertFalse(thread.isAlive()); |
1223 } |
1226 } |
1224 } |
1227 } |
|
1228 |
|
1229 /** |
|
1230 * ThreadMXBean reports the blockers that we expect. |
|
1231 */ |
|
1232 public void testBlockers() { |
|
1233 if (!testImplementationDetails) return; |
|
1234 final boolean fair = randomBoolean(); |
|
1235 final boolean timedAcquire = randomBoolean(); |
|
1236 final boolean timedAwait = randomBoolean(); |
|
1237 final String syncClassName = fair |
|
1238 ? "ReentrantLock$FairSync" |
|
1239 : "ReentrantLock$NonfairSync"; |
|
1240 final String conditionClassName |
|
1241 = "AbstractQueuedSynchronizer$ConditionObject"; |
|
1242 final Thread.State expectedAcquireState = timedAcquire |
|
1243 ? Thread.State.TIMED_WAITING |
|
1244 : Thread.State.WAITING; |
|
1245 final Thread.State expectedAwaitState = timedAwait |
|
1246 ? Thread.State.TIMED_WAITING |
|
1247 : Thread.State.WAITING; |
|
1248 final Lock lock = new ReentrantLock(fair); |
|
1249 final Condition condition = lock.newCondition(); |
|
1250 final AtomicBoolean conditionSatisfied = new AtomicBoolean(false); |
|
1251 lock.lock(); |
|
1252 final Thread thread = newStartedThread((Action) () -> { |
|
1253 if (timedAcquire) |
|
1254 lock.tryLock(LONGER_DELAY_MS, MILLISECONDS); |
|
1255 else |
|
1256 lock.lock(); |
|
1257 while (!conditionSatisfied.get()) |
|
1258 if (timedAwait) |
|
1259 condition.await(LONGER_DELAY_MS, MILLISECONDS); |
|
1260 else |
|
1261 condition.await(); |
|
1262 }); |
|
1263 Callable<Boolean> waitingForLock = () -> { |
|
1264 String className; |
|
1265 return thread.getState() == expectedAcquireState |
|
1266 && (className = blockerClassName(thread)) != null |
|
1267 && className.endsWith(syncClassName); |
|
1268 }; |
|
1269 waitForThreadToEnterWaitState(thread, waitingForLock); |
|
1270 |
|
1271 lock.unlock(); |
|
1272 Callable<Boolean> waitingForCondition = () -> { |
|
1273 String className; |
|
1274 return thread.getState() == expectedAwaitState |
|
1275 && (className = blockerClassName(thread)) != null |
|
1276 && className.endsWith(conditionClassName); |
|
1277 }; |
|
1278 waitForThreadToEnterWaitState(thread, waitingForCondition); |
|
1279 |
|
1280 // politely release the waiter |
|
1281 conditionSatisfied.set(true); |
|
1282 lock.lock(); |
|
1283 try { |
|
1284 condition.signal(); |
|
1285 } finally { lock.unlock(); } |
|
1286 |
|
1287 awaitTermination(thread); |
|
1288 } |
1225 } |
1289 } |