test/jdk/java/util/concurrent/tck/AbstractQueuedSynchronizerTest.java
changeset 58138 1e4270f875ee
parent 51951 1239bfca87f8
equal deleted inserted replaced
58137:6a556bcd94fc 58138:1e4270f875ee
    38 
    38 
    39 import java.util.ArrayList;
    39 import java.util.ArrayList;
    40 import java.util.Arrays;
    40 import java.util.Arrays;
    41 import java.util.Collection;
    41 import java.util.Collection;
    42 import java.util.HashSet;
    42 import java.util.HashSet;
    43 import java.util.concurrent.ThreadLocalRandom;
    43 import java.util.concurrent.atomic.AtomicBoolean;
    44 import java.util.concurrent.locks.AbstractQueuedSynchronizer;
    44 import java.util.concurrent.locks.AbstractQueuedSynchronizer;
    45 import java.util.concurrent.locks.AbstractQueuedSynchronizer.ConditionObject;
    45 import java.util.concurrent.locks.AbstractQueuedSynchronizer.ConditionObject;
    46 
    46 
    47 import junit.framework.Test;
    47 import junit.framework.Test;
    48 import junit.framework.TestSuite;
    48 import junit.framework.TestSuite;
  1335     }
  1335     }
  1336 
  1336 
  1337     /**
  1337     /**
  1338      * Tests scenario for
  1338      * Tests scenario for
  1339      * JDK-8191937: Lost interrupt in AbstractQueuedSynchronizer when tryAcquire methods throw
  1339      * JDK-8191937: Lost interrupt in AbstractQueuedSynchronizer when tryAcquire methods throw
  1340      */
  1340      * ant -Djsr166.tckTestClass=AbstractQueuedSynchronizerTest -Djsr166.methodFilter=testInterruptedFailingAcquire -Djsr166.runsPerTest=10000 tck
  1341     public void testInterruptedFailingAcquire() throws InterruptedException {
  1341      */
  1342         final RuntimeException ex = new RuntimeException();
  1342     public void testInterruptedFailingAcquire() throws Throwable {
       
  1343         class PleaseThrow extends RuntimeException {}
       
  1344         final PleaseThrow ex = new PleaseThrow();
       
  1345         final AtomicBoolean thrown = new AtomicBoolean();
  1343 
  1346 
  1344         // A synchronizer only offering a choice of failure modes
  1347         // A synchronizer only offering a choice of failure modes
  1345         class Sync extends AbstractQueuedSynchronizer {
  1348         class Sync extends AbstractQueuedSynchronizer {
  1346             boolean pleaseThrow;
  1349             volatile boolean pleaseThrow;
       
  1350             void maybeThrow() {
       
  1351                 if (pleaseThrow) {
       
  1352                     // assert: tryAcquire methods can throw at most once
       
  1353                     if (! thrown.compareAndSet(false, true))
       
  1354                         throw new AssertionError();
       
  1355                     throw ex;
       
  1356                 }
       
  1357             }
       
  1358 
  1347             @Override protected boolean tryAcquire(int ignored) {
  1359             @Override protected boolean tryAcquire(int ignored) {
  1348                 if (pleaseThrow) throw ex;
  1360                 maybeThrow();
  1349                 return false;
  1361                 return false;
  1350             }
  1362             }
  1351             @Override protected int tryAcquireShared(int ignored) {
  1363             @Override protected int tryAcquireShared(int ignored) {
  1352                 if (pleaseThrow) throw ex;
  1364                 maybeThrow();
  1353                 return -1;
  1365                 return -1;
  1354             }
  1366             }
  1355             @Override protected boolean tryRelease(int ignored) {
  1367             @Override protected boolean tryRelease(int ignored) {
  1356                 return true;
  1368                 return true;
  1357             }
  1369             }
  1359                 return true;
  1371                 return true;
  1360             }
  1372             }
  1361         }
  1373         }
  1362 
  1374 
  1363         final Sync s = new Sync();
  1375         final Sync s = new Sync();
  1364 
  1376         final boolean acquireInterruptibly = randomBoolean();
       
  1377         final Action[] uninterruptibleAcquireActions = {
       
  1378             () -> s.acquire(1),
       
  1379             () -> s.acquireShared(1),
       
  1380         };
       
  1381         final long nanosTimeout = MILLISECONDS.toNanos(2 * LONG_DELAY_MS);
       
  1382         final Action[] interruptibleAcquireActions = {
       
  1383             () -> s.acquireInterruptibly(1),
       
  1384             () -> s.acquireSharedInterruptibly(1),
       
  1385             () -> s.tryAcquireNanos(1, nanosTimeout),
       
  1386             () -> s.tryAcquireSharedNanos(1, nanosTimeout),
       
  1387         };
       
  1388         final Action[] releaseActions = {
       
  1389             () -> s.release(1),
       
  1390             () -> s.releaseShared(1),
       
  1391         };
       
  1392         final Action acquireAction = acquireInterruptibly
       
  1393             ? chooseRandomly(interruptibleAcquireActions)
       
  1394             : chooseRandomly(uninterruptibleAcquireActions);
       
  1395         final Action releaseAction
       
  1396             = chooseRandomly(releaseActions);
       
  1397 
       
  1398         // From os_posix.cpp:
       
  1399         //
       
  1400         // NOTE that since there is no "lock" around the interrupt and
       
  1401         // is_interrupted operations, there is the possibility that the
       
  1402         // interrupted flag (in osThread) will be "false" but that the
       
  1403         // low-level events will be in the signaled state. This is
       
  1404         // intentional. The effect of this is that Object.wait() and
       
  1405         // LockSupport.park() will appear to have a spurious wakeup, which
       
  1406         // is allowed and not harmful, and the possibility is so rare that
       
  1407         // it is not worth the added complexity to add yet another lock.
  1365         final Thread thread = newStartedThread(new CheckedRunnable() {
  1408         final Thread thread = newStartedThread(new CheckedRunnable() {
  1366             public void realRun() {
  1409             public void realRun() throws Throwable {
  1367                 try {
  1410                 try {
  1368                     if (ThreadLocalRandom.current().nextBoolean())
  1411                     acquireAction.run();
  1369                         s.acquire(1);
       
  1370                     else
       
  1371                         s.acquireShared(1);
       
  1372                     shouldThrow();
  1412                     shouldThrow();
  1373                 } catch (Throwable t) {
  1413                 } catch (InterruptedException possible) {
  1374                     assertSame(ex, t);
  1414                     assertTrue(acquireInterruptibly);
  1375                     assertTrue(Thread.interrupted());
  1415                     assertFalse(Thread.interrupted());
       
  1416                 } catch (PleaseThrow possible) {
       
  1417                     awaitInterrupted();
  1376                 }
  1418                 }
  1377             }});
  1419             }});
  1378         waitForThreadToEnterWaitState(thread);
  1420         for (long startTime = 0L;; ) {
  1379         assertSame(thread, s.getFirstQueuedThread());
  1421             waitForThreadToEnterWaitState(thread);
  1380         assertTrue(s.hasQueuedPredecessors());
  1422             if (s.getFirstQueuedThread() == thread
  1381         assertTrue(s.hasQueuedThreads());
  1423                 && s.hasQueuedPredecessors()
  1382         assertEquals(1, s.getQueueLength());
  1424                 && s.hasQueuedThreads()
       
  1425                 && s.getQueueLength() == 1
       
  1426                 && s.hasContended())
       
  1427                 break;
       
  1428             if (startTime == 0L)
       
  1429                 startTime = System.nanoTime();
       
  1430             else if (millisElapsedSince(startTime) > LONG_DELAY_MS)
       
  1431                 fail("timed out waiting for AQS state: "
       
  1432                      + "thread state=" + thread.getState()
       
  1433                      + ", queued threads=" + s.getQueuedThreads());
       
  1434             Thread.yield();
       
  1435         }
  1383 
  1436 
  1384         s.pleaseThrow = true;
  1437         s.pleaseThrow = true;
  1385         thread.interrupt();
  1438         // release and interrupt, in random order
  1386         s.release(1);
  1439         if (randomBoolean()) {
       
  1440             thread.interrupt();
       
  1441             releaseAction.run();
       
  1442         } else {
       
  1443             releaseAction.run();
       
  1444             thread.interrupt();
       
  1445         }
  1387         awaitTermination(thread);
  1446         awaitTermination(thread);
       
  1447 
       
  1448         if (! acquireInterruptibly)
       
  1449             assertTrue(thrown.get());
       
  1450 
       
  1451         assertNull(s.getFirstQueuedThread());
       
  1452         assertFalse(s.hasQueuedPredecessors());
       
  1453         assertFalse(s.hasQueuedThreads());
       
  1454         assertEquals(0, s.getQueueLength());
       
  1455         assertTrue(s.getQueuedThreads().isEmpty());
       
  1456         assertTrue(s.hasContended());
  1388     }
  1457     }
  1389 
  1458 
  1390 }
  1459 }