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; |
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 |
|
/** |
343 |
|
*/ |
344 |
|
public void testInterruptibleOperationsThrowInterruptedExceptionWriteLockedInterrupted() { |
345 |
|
final StampedLock lock = new StampedLock(); |
346 |
< |
long s = lock.writeLock(); |
346 |
> |
long stamp = lock.writeLock(); |
347 |
|
|
348 |
|
Action[] interruptibleLockBlockingActions = { |
349 |
|
() -> lock.writeLockInterruptibly(), |
358 |
|
shuffle(interruptibleLockBlockingActions); |
359 |
|
|
360 |
|
assertThrowInterruptedExceptionWhenInterrupted(interruptibleLockBlockingActions); |
361 |
+ |
|
362 |
+ |
releaseWriteLock(lock, stamp); |
363 |
|
} |
364 |
|
|
365 |
|
/** |
367 |
|
*/ |
368 |
|
public void testInterruptibleOperationsThrowInterruptedExceptionReadLockedInterrupted() { |
369 |
|
final StampedLock lock = new StampedLock(); |
370 |
< |
long s = lock.readLock(); |
370 |
> |
long stamp = lock.readLock(); |
371 |
|
|
372 |
|
Action[] interruptibleLockBlockingActions = { |
373 |
|
() -> lock.writeLockInterruptibly(), |
378 |
|
shuffle(interruptibleLockBlockingActions); |
379 |
|
|
380 |
|
assertThrowInterruptedExceptionWhenInterrupted(interruptibleLockBlockingActions); |
381 |
+ |
|
382 |
+ |
releaseReadLock(lock, stamp); |
383 |
|
} |
384 |
|
|
385 |
|
/** |
703 |
|
lock.unlockWrite(s); |
704 |
|
s = lock.readLock(); |
705 |
|
assertTrue(lock.toString().contains("Read-locks")); |
706 |
+ |
releaseReadLock(lock, s); |
707 |
|
} |
708 |
|
|
709 |
|
/** |
987 |
|
* IllegalMonitorStateException |
988 |
|
*/ |
989 |
|
public void testCannotUnlockOptimisticReadStamps() { |
990 |
< |
Runnable[] actions = { |
991 |
< |
() -> { |
992 |
< |
StampedLock sl = new StampedLock(); |
993 |
< |
long stamp = assertValid(sl, sl.tryOptimisticRead()); |
994 |
< |
sl.unlockRead(stamp); |
995 |
< |
}, |
996 |
< |
() -> { |
997 |
< |
StampedLock sl = new StampedLock(); |
998 |
< |
long stamp = sl.tryOptimisticRead(); |
999 |
< |
sl.unlock(stamp); |
1000 |
< |
}, |
1001 |
< |
|
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 |
< |
}, |
990 |
> |
{ |
991 |
> |
StampedLock sl = new StampedLock(); |
992 |
> |
long stamp = assertValid(sl, sl.tryOptimisticRead()); |
993 |
> |
assertThrows(IllegalMonitorStateException.class, |
994 |
> |
() -> sl.unlockRead(stamp)); |
995 |
> |
} |
996 |
> |
{ |
997 |
> |
StampedLock sl = new StampedLock(); |
998 |
> |
long stamp = sl.tryOptimisticRead(); |
999 |
> |
assertThrows(IllegalMonitorStateException.class, |
1000 |
> |
() -> sl.unlock(stamp)); |
1001 |
> |
} |
1002 |
|
|
1003 |
< |
() -> { |
1004 |
< |
StampedLock sl = new StampedLock(); |
1005 |
< |
long stamp = sl.tryConvertToOptimisticRead(sl.writeLock()); |
1006 |
< |
assertValid(sl, stamp); |
1007 |
< |
sl.writeLock(); |
1008 |
< |
sl.unlockWrite(stamp); |
1009 |
< |
}, |
1010 |
< |
() -> { |
1011 |
< |
StampedLock sl = new StampedLock(); |
1012 |
< |
long stamp = sl.tryConvertToOptimisticRead(sl.writeLock()); |
1013 |
< |
sl.writeLock(); |
1014 |
< |
sl.unlock(stamp); |
1015 |
< |
}, |
1016 |
< |
() -> { |
1017 |
< |
StampedLock sl = new StampedLock(); |
1018 |
< |
long stamp = sl.tryConvertToOptimisticRead(sl.writeLock()); |
1019 |
< |
sl.readLock(); |
1020 |
< |
sl.unlockRead(stamp); |
1021 |
< |
}, |
1022 |
< |
() -> { |
1023 |
< |
StampedLock sl = new StampedLock(); |
1037 |
< |
long stamp = sl.tryConvertToOptimisticRead(sl.writeLock()); |
1038 |
< |
sl.readLock(); |
1039 |
< |
sl.unlock(stamp); |
1040 |
< |
}, |
1003 |
> |
{ |
1004 |
> |
StampedLock sl = new StampedLock(); |
1005 |
> |
long stamp = sl.tryOptimisticRead(); |
1006 |
> |
sl.writeLock(); |
1007 |
> |
assertThrows(IllegalMonitorStateException.class, |
1008 |
> |
() -> sl.unlock(stamp)); |
1009 |
> |
} |
1010 |
> |
{ |
1011 |
> |
StampedLock sl = new StampedLock(); |
1012 |
> |
sl.readLock(); |
1013 |
> |
long stamp = assertValid(sl, sl.tryOptimisticRead()); |
1014 |
> |
assertThrows(IllegalMonitorStateException.class, |
1015 |
> |
() -> sl.unlockRead(stamp)); |
1016 |
> |
} |
1017 |
> |
{ |
1018 |
> |
StampedLock sl = new StampedLock(); |
1019 |
> |
sl.readLock(); |
1020 |
> |
long stamp = assertValid(sl, sl.tryOptimisticRead()); |
1021 |
> |
assertThrows(IllegalMonitorStateException.class, |
1022 |
> |
() -> sl.unlock(stamp)); |
1023 |
> |
} |
1024 |
|
|
1025 |
< |
() -> { |
1026 |
< |
StampedLock sl = new StampedLock(); |
1027 |
< |
long stamp = sl.tryConvertToOptimisticRead(sl.readLock()); |
1028 |
< |
assertValid(sl, stamp); |
1029 |
< |
sl.writeLock(); |
1030 |
< |
sl.unlockWrite(stamp); |
1031 |
< |
}, |
1032 |
< |
() -> { |
1033 |
< |
StampedLock sl = new StampedLock(); |
1034 |
< |
long stamp = sl.tryConvertToOptimisticRead(sl.readLock()); |
1035 |
< |
sl.writeLock(); |
1036 |
< |
sl.unlock(stamp); |
1037 |
< |
}, |
1038 |
< |
() -> { |
1039 |
< |
StampedLock sl = new StampedLock(); |
1040 |
< |
long stamp = sl.tryConvertToOptimisticRead(sl.readLock()); |
1041 |
< |
sl.readLock(); |
1042 |
< |
sl.unlockRead(stamp); |
1043 |
< |
}, |
1044 |
< |
() -> { |
1045 |
< |
StampedLock sl = new StampedLock(); |
1046 |
< |
sl.readLock(); |
1047 |
< |
long stamp = sl.tryConvertToOptimisticRead(sl.readLock()); |
1048 |
< |
assertValid(sl, stamp); |
1049 |
< |
sl.readLock(); |
1050 |
< |
sl.unlockRead(stamp); |
1051 |
< |
}, |
1052 |
< |
() -> { |
1053 |
< |
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 |
< |
}; |
1025 |
> |
{ |
1026 |
> |
StampedLock sl = new StampedLock(); |
1027 |
> |
long stamp = sl.tryConvertToOptimisticRead(sl.writeLock()); |
1028 |
> |
assertValid(sl, stamp); |
1029 |
> |
sl.writeLock(); |
1030 |
> |
assertThrows(IllegalMonitorStateException.class, |
1031 |
> |
() -> sl.unlockWrite(stamp)); |
1032 |
> |
} |
1033 |
> |
{ |
1034 |
> |
StampedLock sl = new StampedLock(); |
1035 |
> |
long stamp = sl.tryConvertToOptimisticRead(sl.writeLock()); |
1036 |
> |
sl.writeLock(); |
1037 |
> |
assertThrows(IllegalMonitorStateException.class, |
1038 |
> |
() -> sl.unlock(stamp)); |
1039 |
> |
} |
1040 |
> |
{ |
1041 |
> |
StampedLock sl = new StampedLock(); |
1042 |
> |
long stamp = sl.tryConvertToOptimisticRead(sl.writeLock()); |
1043 |
> |
sl.readLock(); |
1044 |
> |
assertThrows(IllegalMonitorStateException.class, |
1045 |
> |
() -> sl.unlockRead(stamp)); |
1046 |
> |
} |
1047 |
> |
{ |
1048 |
> |
StampedLock sl = new StampedLock(); |
1049 |
> |
long stamp = sl.tryConvertToOptimisticRead(sl.writeLock()); |
1050 |
> |
sl.readLock(); |
1051 |
> |
assertThrows(IllegalMonitorStateException.class, |
1052 |
> |
() -> sl.unlock(stamp)); |
1053 |
> |
} |
1054 |
|
|
1055 |
< |
assertThrows(IllegalMonitorStateException.class, actions); |
1055 |
> |
{ |
1056 |
> |
StampedLock sl = new StampedLock(); |
1057 |
> |
long stamp = sl.tryConvertToOptimisticRead(sl.readLock()); |
1058 |
> |
assertValid(sl, stamp); |
1059 |
> |
sl.writeLock(); |
1060 |
> |
assertThrows(IllegalMonitorStateException.class, |
1061 |
> |
() -> sl.unlockWrite(stamp)); |
1062 |
> |
} |
1063 |
> |
{ |
1064 |
> |
StampedLock sl = new StampedLock(); |
1065 |
> |
long stamp = sl.tryConvertToOptimisticRead(sl.readLock()); |
1066 |
> |
sl.writeLock(); |
1067 |
> |
assertThrows(IllegalMonitorStateException.class, |
1068 |
> |
() -> sl.unlock(stamp)); |
1069 |
> |
} |
1070 |
> |
{ |
1071 |
> |
StampedLock sl = new StampedLock(); |
1072 |
> |
long stamp = sl.tryConvertToOptimisticRead(sl.readLock()); |
1073 |
> |
sl.readLock(); |
1074 |
> |
assertThrows(IllegalMonitorStateException.class, |
1075 |
> |
() -> sl.unlockRead(stamp)); |
1076 |
> |
} |
1077 |
> |
{ |
1078 |
> |
StampedLock sl = new StampedLock(); |
1079 |
> |
sl.readLock(); |
1080 |
> |
long stamp = sl.tryConvertToOptimisticRead(sl.readLock()); |
1081 |
> |
assertValid(sl, stamp); |
1082 |
> |
sl.readLock(); |
1083 |
> |
assertThrows(IllegalMonitorStateException.class, |
1084 |
> |
() -> sl.unlockRead(stamp)); |
1085 |
> |
} |
1086 |
> |
{ |
1087 |
> |
StampedLock sl = new StampedLock(); |
1088 |
> |
long stamp = sl.tryConvertToOptimisticRead(sl.readLock()); |
1089 |
> |
sl.readLock(); |
1090 |
> |
assertThrows(IllegalMonitorStateException.class, |
1091 |
> |
() -> sl.unlock(stamp)); |
1092 |
> |
} |
1093 |
> |
{ |
1094 |
> |
StampedLock sl = new StampedLock(); |
1095 |
> |
sl.readLock(); |
1096 |
> |
long stamp = sl.tryConvertToOptimisticRead(sl.readLock()); |
1097 |
> |
sl.readLock(); |
1098 |
> |
assertThrows(IllegalMonitorStateException.class, |
1099 |
> |
() -> sl.unlock(stamp)); |
1100 |
> |
} |
1101 |
|
} |
1102 |
|
|
1103 |
|
static long writeLockInterruptiblyUninterrupted(StampedLock sl) { |
1391 |
|
} |
1392 |
|
} |
1393 |
|
|
1394 |
+ |
/** |
1395 |
+ |
* Multiple threads repeatedly contend for the same lock. |
1396 |
+ |
*/ |
1397 |
+ |
public void testConcurrentAccess() throws Exception { |
1398 |
+ |
final StampedLock sl = new StampedLock(); |
1399 |
+ |
final Lock wl = sl.asWriteLock(); |
1400 |
+ |
final Lock rl = sl.asReadLock(); |
1401 |
+ |
final long testDurationMillis = expensiveTests ? 1000 : 2; |
1402 |
+ |
final int nTasks = ThreadLocalRandom.current().nextInt(1, 10); |
1403 |
+ |
final AtomicBoolean done = new AtomicBoolean(false); |
1404 |
+ |
final List<CompletableFuture> futures = new ArrayList<>(); |
1405 |
+ |
final List<Callable<Long>> stampedWriteLockers = List.of( |
1406 |
+ |
() -> sl.writeLock(), |
1407 |
+ |
() -> writeLockInterruptiblyUninterrupted(sl), |
1408 |
+ |
() -> tryWriteLockUninterrupted(sl, LONG_DELAY_MS, MILLISECONDS), |
1409 |
+ |
() -> { |
1410 |
+ |
long stamp; |
1411 |
+ |
do { stamp = sl.tryConvertToWriteLock(sl.tryOptimisticRead()); } |
1412 |
+ |
while (stamp == 0L); |
1413 |
+ |
return stamp; |
1414 |
+ |
}, |
1415 |
+ |
() -> { |
1416 |
+ |
long stamp; |
1417 |
+ |
do { stamp = sl.tryWriteLock(); } while (stamp == 0L); |
1418 |
+ |
return stamp; |
1419 |
+ |
}, |
1420 |
+ |
() -> { |
1421 |
+ |
long stamp; |
1422 |
+ |
do { stamp = sl.tryWriteLock(0L, DAYS); } while (stamp == 0L); |
1423 |
+ |
return stamp; |
1424 |
+ |
}); |
1425 |
+ |
final List<Callable<Long>> stampedReadLockers = List.of( |
1426 |
+ |
() -> sl.readLock(), |
1427 |
+ |
() -> readLockInterruptiblyUninterrupted(sl), |
1428 |
+ |
() -> tryReadLockUninterrupted(sl, LONG_DELAY_MS, MILLISECONDS), |
1429 |
+ |
() -> { |
1430 |
+ |
long stamp; |
1431 |
+ |
do { stamp = sl.tryConvertToReadLock(sl.tryOptimisticRead()); } |
1432 |
+ |
while (stamp == 0L); |
1433 |
+ |
return stamp; |
1434 |
+ |
}, |
1435 |
+ |
() -> { |
1436 |
+ |
long stamp; |
1437 |
+ |
do { stamp = sl.tryReadLock(); } while (stamp == 0L); |
1438 |
+ |
return stamp; |
1439 |
+ |
}, |
1440 |
+ |
() -> { |
1441 |
+ |
long stamp; |
1442 |
+ |
do { stamp = sl.tryReadLock(0L, DAYS); } while (stamp == 0L); |
1443 |
+ |
return stamp; |
1444 |
+ |
}); |
1445 |
+ |
final List<Consumer<Long>> stampedWriteUnlockers = List.of( |
1446 |
+ |
stamp -> sl.unlockWrite(stamp), |
1447 |
+ |
stamp -> sl.unlock(stamp), |
1448 |
+ |
stamp -> assertTrue(sl.tryUnlockWrite()), |
1449 |
+ |
stamp -> wl.unlock(), |
1450 |
+ |
stamp -> sl.tryConvertToOptimisticRead(stamp)); |
1451 |
+ |
final List<Consumer<Long>> stampedReadUnlockers = List.of( |
1452 |
+ |
stamp -> sl.unlockRead(stamp), |
1453 |
+ |
stamp -> sl.unlock(stamp), |
1454 |
+ |
stamp -> assertTrue(sl.tryUnlockRead()), |
1455 |
+ |
stamp -> rl.unlock(), |
1456 |
+ |
stamp -> sl.tryConvertToOptimisticRead(stamp)); |
1457 |
+ |
final Action writer = () -> { |
1458 |
+ |
// repeatedly acquires write lock |
1459 |
+ |
var locker = chooseRandomly(stampedWriteLockers); |
1460 |
+ |
var unlocker = chooseRandomly(stampedWriteUnlockers); |
1461 |
+ |
while (!done.getAcquire()) { |
1462 |
+ |
long stamp = locker.call(); |
1463 |
+ |
try { |
1464 |
+ |
assertTrue(isWriteLockStamp(stamp)); |
1465 |
+ |
assertTrue(sl.isWriteLocked()); |
1466 |
+ |
assertFalse(isReadLockStamp(stamp)); |
1467 |
+ |
assertFalse(sl.isReadLocked()); |
1468 |
+ |
assertEquals(0, sl.getReadLockCount()); |
1469 |
+ |
assertTrue(sl.validate(stamp)); |
1470 |
+ |
} finally { |
1471 |
+ |
unlocker.accept(stamp); |
1472 |
+ |
} |
1473 |
+ |
} |
1474 |
+ |
}; |
1475 |
+ |
final Action reader = () -> { |
1476 |
+ |
// repeatedly acquires read lock |
1477 |
+ |
var locker = chooseRandomly(stampedReadLockers); |
1478 |
+ |
var unlocker = chooseRandomly(stampedReadUnlockers); |
1479 |
+ |
while (!done.getAcquire()) { |
1480 |
+ |
long stamp = locker.call(); |
1481 |
+ |
try { |
1482 |
+ |
assertFalse(isWriteLockStamp(stamp)); |
1483 |
+ |
assertFalse(sl.isWriteLocked()); |
1484 |
+ |
assertTrue(isReadLockStamp(stamp)); |
1485 |
+ |
assertTrue(sl.isReadLocked()); |
1486 |
+ |
assertTrue(sl.getReadLockCount() > 0); |
1487 |
+ |
assertTrue(sl.validate(stamp)); |
1488 |
+ |
} finally { |
1489 |
+ |
unlocker.accept(stamp); |
1490 |
+ |
} |
1491 |
+ |
} |
1492 |
+ |
}; |
1493 |
+ |
for (int i = nTasks; i--> 0; ) { |
1494 |
+ |
Action task = chooseRandomly(writer, reader); |
1495 |
+ |
futures.add(CompletableFuture.runAsync(checkedRunnable(task))); |
1496 |
+ |
} |
1497 |
+ |
Thread.sleep(testDurationMillis); |
1498 |
+ |
done.setRelease(true); |
1499 |
+ |
for (var future : futures) |
1500 |
+ |
checkTimedGet(future, null); |
1501 |
+ |
} |
1502 |
+ |
|
1503 |
|
} |