ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/jsr166/jsr166/src/test/tck/StampedLockTest.java
(Generate patch)

Comparing jsr166/src/test/tck/StampedLockTest.java (file contents):
Revision 1.42 by jsr166, Mon Nov 27 23:38:11 2017 UTC vs.
Revision 1.44 by jsr166, Sun Sep 29 20:19:43 2019 UTC

# Line 15 | Line 15 | import static java.util.concurrent.locks
15  
16   import java.util.ArrayList;
17   import java.util.List;
18 + import java.util.concurrent.Callable;
19 + import java.util.concurrent.CompletableFuture;
20   import java.util.concurrent.CountDownLatch;
21   import java.util.concurrent.Future;
22 + import java.util.concurrent.ThreadLocalRandom;
23   import java.util.concurrent.TimeUnit;
24 + import java.util.concurrent.atomic.AtomicBoolean;
25   import java.util.concurrent.locks.Lock;
26   import java.util.concurrent.locks.StampedLock;
27   import java.util.function.BiConsumer;
28 + import java.util.function.Consumer;
29   import java.util.function.Function;
30  
31   import junit.framework.Test;
# Line 75 | Line 80 | public class StampedLockTest extends JSR
80      }
81  
82      List<Action> lockLockers(Lock lock) {
83 <        List<Action> lockers = new ArrayList<>();
84 <        lockers.add(() -> lock.lock());
85 <        lockers.add(() -> lock.lockInterruptibly());
86 <        lockers.add(() -> lock.tryLock());
87 <        lockers.add(() -> lock.tryLock(Long.MIN_VALUE, DAYS));
88 <        lockers.add(() -> lock.tryLock(0L, DAYS));
89 <        lockers.add(() -> lock.tryLock(Long.MAX_VALUE, DAYS));
85 <        return lockers;
83 >        return List.of(
84 >            () -> lock.lock(),
85 >            () -> lock.lockInterruptibly(),
86 >            () -> lock.tryLock(),
87 >            () -> lock.tryLock(Long.MIN_VALUE, DAYS),
88 >            () -> lock.tryLock(0L, DAYS),
89 >            () -> lock.tryLock(Long.MAX_VALUE, DAYS));
90      }
91  
92      List<Function<StampedLock, Long>> readLockers() {
93 <        List<Function<StampedLock, Long>> readLockers = new ArrayList<>();
94 <        readLockers.add(sl -> sl.readLock());
95 <        readLockers.add(sl -> sl.tryReadLock());
96 <        readLockers.add(sl -> readLockInterruptiblyUninterrupted(sl));
97 <        readLockers.add(sl -> tryReadLockUninterrupted(sl, Long.MIN_VALUE, DAYS));
98 <        readLockers.add(sl -> tryReadLockUninterrupted(sl, 0L, DAYS));
99 <        readLockers.add(sl -> sl.tryConvertToReadLock(sl.tryOptimisticRead()));
96 <        return readLockers;
93 >        return List.of(
94 >            sl -> sl.readLock(),
95 >            sl -> sl.tryReadLock(),
96 >            sl -> readLockInterruptiblyUninterrupted(sl),
97 >            sl -> tryReadLockUninterrupted(sl, Long.MIN_VALUE, DAYS),
98 >            sl -> tryReadLockUninterrupted(sl, 0L, DAYS),
99 >            sl -> sl.tryConvertToReadLock(sl.tryOptimisticRead()));
100      }
101  
102      List<BiConsumer<StampedLock, Long>> readUnlockers() {
103 <        List<BiConsumer<StampedLock, Long>> readUnlockers = new ArrayList<>();
104 <        readUnlockers.add((sl, stamp) -> sl.unlockRead(stamp));
105 <        readUnlockers.add((sl, stamp) -> assertTrue(sl.tryUnlockRead()));
106 <        readUnlockers.add((sl, stamp) -> sl.asReadLock().unlock());
107 <        readUnlockers.add((sl, stamp) -> sl.unlock(stamp));
108 <        readUnlockers.add((sl, stamp) -> assertValid(sl, sl.tryConvertToOptimisticRead(stamp)));
106 <        return readUnlockers;
103 >        return List.of(
104 >            (sl, stamp) -> sl.unlockRead(stamp),
105 >            (sl, stamp) -> assertTrue(sl.tryUnlockRead()),
106 >            (sl, stamp) -> sl.asReadLock().unlock(),
107 >            (sl, stamp) -> sl.unlock(stamp),
108 >            (sl, stamp) -> assertValid(sl, sl.tryConvertToOptimisticRead(stamp)));
109      }
110  
111      List<Function<StampedLock, Long>> writeLockers() {
112 <        List<Function<StampedLock, Long>> writeLockers = new ArrayList<>();
113 <        writeLockers.add(sl -> sl.writeLock());
114 <        writeLockers.add(sl -> sl.tryWriteLock());
115 <        writeLockers.add(sl -> writeLockInterruptiblyUninterrupted(sl));
116 <        writeLockers.add(sl -> tryWriteLockUninterrupted(sl, Long.MIN_VALUE, DAYS));
117 <        writeLockers.add(sl -> tryWriteLockUninterrupted(sl, 0L, DAYS));
118 <        writeLockers.add(sl -> sl.tryConvertToWriteLock(sl.tryOptimisticRead()));
117 <        return writeLockers;
112 >        return List.of(
113 >            sl -> sl.writeLock(),
114 >            sl -> sl.tryWriteLock(),
115 >            sl -> writeLockInterruptiblyUninterrupted(sl),
116 >            sl -> tryWriteLockUninterrupted(sl, Long.MIN_VALUE, DAYS),
117 >            sl -> tryWriteLockUninterrupted(sl, 0L, DAYS),
118 >            sl -> sl.tryConvertToWriteLock(sl.tryOptimisticRead()));
119      }
120  
121      List<BiConsumer<StampedLock, Long>> writeUnlockers() {
122 <        List<BiConsumer<StampedLock, Long>> writeUnlockers = new ArrayList<>();
123 <        writeUnlockers.add((sl, stamp) -> sl.unlockWrite(stamp));
124 <        writeUnlockers.add((sl, stamp) -> assertTrue(sl.tryUnlockWrite()));
125 <        writeUnlockers.add((sl, stamp) -> sl.asWriteLock().unlock());
126 <        writeUnlockers.add((sl, stamp) -> sl.unlock(stamp));
127 <        writeUnlockers.add((sl, stamp) -> assertValid(sl, sl.tryConvertToOptimisticRead(stamp)));
127 <        return writeUnlockers;
122 >        return List.of(
123 >            (sl, stamp) -> sl.unlockWrite(stamp),
124 >            (sl, stamp) -> assertTrue(sl.tryUnlockWrite()),
125 >            (sl, stamp) -> sl.asWriteLock().unlock(),
126 >            (sl, stamp) -> sl.unlock(stamp),
127 >            (sl, stamp) -> assertValid(sl, sl.tryConvertToOptimisticRead(stamp)));
128      }
129  
130      /**
# Line 982 | Line 982 | public class StampedLockTest extends JSR
982       * IllegalMonitorStateException
983       */
984      public void testCannotUnlockOptimisticReadStamps() {
985 <        Runnable[] actions = {
986 <            () -> {
987 <                StampedLock sl = new StampedLock();
988 <                long stamp = assertValid(sl, sl.tryOptimisticRead());
989 <                sl.unlockRead(stamp);
990 <            },
991 <            () -> {
992 <                StampedLock sl = new StampedLock();
993 <                long stamp = sl.tryOptimisticRead();
994 <                sl.unlock(stamp);
995 <            },
996 <
997 <            () -> {
998 <                StampedLock sl = new StampedLock();
999 <                long stamp = sl.tryOptimisticRead();
1000 <                sl.writeLock();
1001 <                sl.unlock(stamp);
1002 <            },
1003 <            () -> {
1004 <                StampedLock sl = new StampedLock();
1005 <                sl.readLock();
1006 <                long stamp = assertValid(sl, sl.tryOptimisticRead());
1007 <                sl.unlockRead(stamp);
1008 <            },
1009 <            () -> {
1010 <                StampedLock sl = new StampedLock();
1011 <                sl.readLock();
1012 <                long stamp = assertValid(sl, sl.tryOptimisticRead());
1013 <                sl.unlock(stamp);
1014 <            },
985 >        {
986 >            StampedLock sl = new StampedLock();
987 >            long stamp = assertValid(sl, sl.tryOptimisticRead());
988 >            assertThrows(IllegalMonitorStateException.class,
989 >                () -> sl.unlockRead(stamp));
990 >        }
991 >        {
992 >            StampedLock sl = new StampedLock();
993 >            long stamp = sl.tryOptimisticRead();
994 >            assertThrows(IllegalMonitorStateException.class,
995 >                () -> sl.unlock(stamp));
996 >        }
997  
998 <            () -> {
999 <                StampedLock sl = new StampedLock();
1000 <                long stamp = sl.tryConvertToOptimisticRead(sl.writeLock());
1001 <                assertValid(sl, stamp);
1002 <                sl.writeLock();
1003 <                sl.unlockWrite(stamp);
1004 <            },
1005 <            () -> {
1006 <                StampedLock sl = new StampedLock();
1007 <                long stamp = sl.tryConvertToOptimisticRead(sl.writeLock());
1008 <                sl.writeLock();
1009 <                sl.unlock(stamp);
1010 <            },
1011 <            () -> {
1012 <                StampedLock sl = new StampedLock();
1013 <                long stamp = sl.tryConvertToOptimisticRead(sl.writeLock());
1014 <                sl.readLock();
1015 <                sl.unlockRead(stamp);
1016 <            },
1017 <            () -> {
1018 <                StampedLock sl = new StampedLock();
1037 <                long stamp = sl.tryConvertToOptimisticRead(sl.writeLock());
1038 <                sl.readLock();
1039 <                sl.unlock(stamp);
1040 <            },
998 >        {
999 >            StampedLock sl = new StampedLock();
1000 >            long stamp = sl.tryOptimisticRead();
1001 >            sl.writeLock();
1002 >            assertThrows(IllegalMonitorStateException.class,
1003 >                () -> sl.unlock(stamp));
1004 >        }
1005 >        {
1006 >            StampedLock sl = new StampedLock();
1007 >            sl.readLock();
1008 >            long stamp = assertValid(sl, sl.tryOptimisticRead());
1009 >            assertThrows(IllegalMonitorStateException.class,
1010 >                () -> sl.unlockRead(stamp));
1011 >        }
1012 >        {
1013 >            StampedLock sl = new StampedLock();
1014 >            sl.readLock();
1015 >            long stamp = assertValid(sl, sl.tryOptimisticRead());
1016 >            assertThrows(IllegalMonitorStateException.class,
1017 >                () -> sl.unlock(stamp));
1018 >        }
1019  
1020 <            () -> {
1021 <                StampedLock sl = new StampedLock();
1022 <                long stamp = sl.tryConvertToOptimisticRead(sl.readLock());
1023 <                assertValid(sl, stamp);
1024 <                sl.writeLock();
1025 <                sl.unlockWrite(stamp);
1026 <            },
1027 <            () -> {
1028 <                StampedLock sl = new StampedLock();
1029 <                long stamp = sl.tryConvertToOptimisticRead(sl.readLock());
1030 <                sl.writeLock();
1031 <                sl.unlock(stamp);
1032 <            },
1033 <            () -> {
1034 <                StampedLock sl = new StampedLock();
1035 <                long stamp = sl.tryConvertToOptimisticRead(sl.readLock());
1036 <                sl.readLock();
1037 <                sl.unlockRead(stamp);
1038 <            },
1039 <            () -> {
1040 <                StampedLock sl = new StampedLock();
1041 <                sl.readLock();
1042 <                long stamp = sl.tryConvertToOptimisticRead(sl.readLock());
1043 <                assertValid(sl, stamp);
1044 <                sl.readLock();
1045 <                sl.unlockRead(stamp);
1046 <            },
1047 <            () -> {
1048 <                StampedLock sl = new StampedLock();
1071 <                long stamp = sl.tryConvertToOptimisticRead(sl.readLock());
1072 <                sl.readLock();
1073 <                sl.unlock(stamp);
1074 <            },
1075 <            () -> {
1076 <                StampedLock sl = new StampedLock();
1077 <                sl.readLock();
1078 <                long stamp = sl.tryConvertToOptimisticRead(sl.readLock());
1079 <                sl.readLock();
1080 <                sl.unlock(stamp);
1081 <            },
1082 <        };
1020 >        {
1021 >            StampedLock sl = new StampedLock();
1022 >            long stamp = sl.tryConvertToOptimisticRead(sl.writeLock());
1023 >            assertValid(sl, stamp);
1024 >            sl.writeLock();
1025 >            assertThrows(IllegalMonitorStateException.class,
1026 >                () -> sl.unlockWrite(stamp));
1027 >        }
1028 >        {
1029 >            StampedLock sl = new StampedLock();
1030 >            long stamp = sl.tryConvertToOptimisticRead(sl.writeLock());
1031 >            sl.writeLock();
1032 >            assertThrows(IllegalMonitorStateException.class,
1033 >                () -> sl.unlock(stamp));
1034 >        }
1035 >        {
1036 >            StampedLock sl = new StampedLock();
1037 >            long stamp = sl.tryConvertToOptimisticRead(sl.writeLock());
1038 >            sl.readLock();
1039 >            assertThrows(IllegalMonitorStateException.class,
1040 >                () -> sl.unlockRead(stamp));
1041 >        }
1042 >        {
1043 >            StampedLock sl = new StampedLock();
1044 >            long stamp = sl.tryConvertToOptimisticRead(sl.writeLock());
1045 >            sl.readLock();
1046 >            assertThrows(IllegalMonitorStateException.class,
1047 >                () -> sl.unlock(stamp));
1048 >        }
1049  
1050 <        assertThrows(IllegalMonitorStateException.class, actions);
1050 >        {
1051 >            StampedLock sl = new StampedLock();
1052 >            long stamp = sl.tryConvertToOptimisticRead(sl.readLock());
1053 >            assertValid(sl, stamp);
1054 >            sl.writeLock();
1055 >            assertThrows(IllegalMonitorStateException.class,
1056 >                () -> sl.unlockWrite(stamp));
1057 >            }
1058 >        {
1059 >            StampedLock sl = new StampedLock();
1060 >            long stamp = sl.tryConvertToOptimisticRead(sl.readLock());
1061 >            sl.writeLock();
1062 >            assertThrows(IllegalMonitorStateException.class,
1063 >                () -> sl.unlock(stamp));
1064 >        }
1065 >        {
1066 >            StampedLock sl = new StampedLock();
1067 >            long stamp = sl.tryConvertToOptimisticRead(sl.readLock());
1068 >            sl.readLock();
1069 >            assertThrows(IllegalMonitorStateException.class,
1070 >                () -> sl.unlockRead(stamp));
1071 >        }
1072 >        {
1073 >            StampedLock sl = new StampedLock();
1074 >            sl.readLock();
1075 >            long stamp = sl.tryConvertToOptimisticRead(sl.readLock());
1076 >            assertValid(sl, stamp);
1077 >            sl.readLock();
1078 >            assertThrows(IllegalMonitorStateException.class,
1079 >                () -> sl.unlockRead(stamp));
1080 >        }
1081 >        {
1082 >            StampedLock sl = new StampedLock();
1083 >            long stamp = sl.tryConvertToOptimisticRead(sl.readLock());
1084 >            sl.readLock();
1085 >            assertThrows(IllegalMonitorStateException.class,
1086 >                () -> sl.unlock(stamp));
1087 >        }
1088 >        {
1089 >            StampedLock sl = new StampedLock();
1090 >            sl.readLock();
1091 >            long stamp = sl.tryConvertToOptimisticRead(sl.readLock());
1092 >            sl.readLock();
1093 >            assertThrows(IllegalMonitorStateException.class,
1094 >                () -> sl.unlock(stamp));
1095 >        }
1096      }
1097  
1098      static long writeLockInterruptiblyUninterrupted(StampedLock sl) {
# Line 1375 | Line 1386 | public class StampedLockTest extends JSR
1386          }
1387      }
1388  
1389 +    /**
1390 +     * Multiple threads repeatedly contend for the same lock.
1391 +     */
1392 +    public void testConcurrentAccess() throws Exception {
1393 +        final StampedLock sl = new StampedLock();
1394 +        final Lock wl = sl.asWriteLock();
1395 +        final Lock rl = sl.asReadLock();
1396 +        final long testDurationMillis = expensiveTests ? 1000 : 2;
1397 +        final int nTasks = ThreadLocalRandom.current().nextInt(1, 10);
1398 +        final AtomicBoolean done = new AtomicBoolean(false);
1399 +        final List<CompletableFuture> futures = new ArrayList<>();
1400 +        final List<Callable<Long>> stampedWriteLockers = List.of(
1401 +            () -> sl.writeLock(),
1402 +            () -> writeLockInterruptiblyUninterrupted(sl),
1403 +            () -> tryWriteLockUninterrupted(sl, LONG_DELAY_MS, MILLISECONDS),
1404 +            () -> {
1405 +                long stamp;
1406 +                do { stamp = sl.tryConvertToWriteLock(sl.tryOptimisticRead()); }
1407 +                while (stamp == 0L);
1408 +                return stamp;
1409 +            },
1410 +            () -> {
1411 +              long stamp;
1412 +              do { stamp = sl.tryWriteLock(); } while (stamp == 0L);
1413 +              return stamp;
1414 +            },
1415 +            () -> {
1416 +              long stamp;
1417 +              do { stamp = sl.tryWriteLock(0L, DAYS); } while (stamp == 0L);
1418 +              return stamp;
1419 +            });
1420 +        final List<Callable<Long>> stampedReadLockers = List.of(
1421 +            () -> sl.readLock(),
1422 +            () -> readLockInterruptiblyUninterrupted(sl),
1423 +            () -> tryReadLockUninterrupted(sl, LONG_DELAY_MS, MILLISECONDS),
1424 +            () -> {
1425 +                long stamp;
1426 +                do { stamp = sl.tryConvertToReadLock(sl.tryOptimisticRead()); }
1427 +                while (stamp == 0L);
1428 +                return stamp;
1429 +            },
1430 +            () -> {
1431 +              long stamp;
1432 +              do { stamp = sl.tryReadLock(); } while (stamp == 0L);
1433 +              return stamp;
1434 +            },
1435 +            () -> {
1436 +              long stamp;
1437 +              do { stamp = sl.tryReadLock(0L, DAYS); } while (stamp == 0L);
1438 +              return stamp;
1439 +            });
1440 +        final List<Consumer<Long>> stampedWriteUnlockers = List.of(
1441 +            stamp -> sl.unlockWrite(stamp),
1442 +            stamp -> sl.unlock(stamp),
1443 +            stamp -> assertTrue(sl.tryUnlockWrite()),
1444 +            stamp -> wl.unlock(),
1445 +            stamp -> sl.tryConvertToOptimisticRead(stamp));
1446 +        final List<Consumer<Long>> stampedReadUnlockers = List.of(
1447 +            stamp -> sl.unlockRead(stamp),
1448 +            stamp -> sl.unlock(stamp),
1449 +            stamp -> assertTrue(sl.tryUnlockRead()),
1450 +            stamp -> rl.unlock(),
1451 +            stamp -> sl.tryConvertToOptimisticRead(stamp));
1452 +        final Action writer = () -> {
1453 +            // repeatedly acquires write lock
1454 +            var locker = chooseRandomly(stampedWriteLockers);
1455 +            var unlocker = chooseRandomly(stampedWriteUnlockers);
1456 +            while (!done.getAcquire()) {
1457 +                long stamp = locker.call();
1458 +                try {
1459 +                    assertTrue(isWriteLockStamp(stamp));
1460 +                    assertTrue(sl.isWriteLocked());
1461 +                    assertFalse(isReadLockStamp(stamp));
1462 +                    assertFalse(sl.isReadLocked());
1463 +                    assertEquals(0, sl.getReadLockCount());
1464 +                    assertTrue(sl.validate(stamp));
1465 +                } finally {
1466 +                    unlocker.accept(stamp);
1467 +                }
1468 +            }
1469 +        };
1470 +        final Action reader = () -> {
1471 +            // repeatedly acquires read lock
1472 +            var locker = chooseRandomly(stampedReadLockers);
1473 +            var unlocker = chooseRandomly(stampedReadUnlockers);
1474 +            while (!done.getAcquire()) {
1475 +                long stamp = locker.call();
1476 +                try {
1477 +                    assertFalse(isWriteLockStamp(stamp));
1478 +                    assertFalse(sl.isWriteLocked());
1479 +                    assertTrue(isReadLockStamp(stamp));
1480 +                    assertTrue(sl.isReadLocked());
1481 +                    assertTrue(sl.getReadLockCount() > 0);
1482 +                    assertTrue(sl.validate(stamp));
1483 +                } finally {
1484 +                    unlocker.accept(stamp);
1485 +                }
1486 +            }
1487 +        };
1488 +        for (int i = nTasks; i--> 0; ) {
1489 +            Action task = chooseRandomly(writer, reader);
1490 +            futures.add(CompletableFuture.runAsync(checkedRunnable(task)));
1491 +        }
1492 +        Thread.sleep(testDurationMillis);
1493 +        done.setRelease(true);
1494 +        for (var future : futures)
1495 +            checkTimedGet(future, null);
1496 +    }
1497 +
1498   }

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines