ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/jsr166/jsr166/src/test/tck/StampedLockTest.java
Revision: 1.31
Committed: Sat Feb 18 00:34:52 2017 UTC (7 years, 2 months ago) by jsr166
Branch: MAIN
Changes since 1.30: +3 -3 lines
Log Message:
testWriteAfterReadLock: improve local variable name

File Contents

# Content
1 /*
2 * Written by Doug Lea and Martin Buchholz
3 * with assistance from members of JCP JSR-166 Expert Group and
4 * released to the public domain, as explained at
5 * http://creativecommons.org/publicdomain/zero/1.0/
6 */
7
8 import static java.util.concurrent.TimeUnit.DAYS;
9 import static java.util.concurrent.TimeUnit.MILLISECONDS;
10 import static java.util.concurrent.TimeUnit.SECONDS;
11
12 import java.util.ArrayList;
13 import java.util.List;
14 import java.util.concurrent.CountDownLatch;
15 import java.util.concurrent.Future;
16 import java.util.concurrent.TimeUnit;
17 import java.util.concurrent.locks.Lock;
18 import java.util.concurrent.locks.StampedLock;
19 import java.util.function.BiConsumer;
20 import java.util.function.Function;
21
22 import junit.framework.Test;
23 import junit.framework.TestSuite;
24
25 public class StampedLockTest extends JSR166TestCase {
26 public static void main(String[] args) {
27 main(suite(), args);
28 }
29 public static Test suite() {
30 return new TestSuite(StampedLockTest.class);
31 }
32
33 /**
34 * Releases write lock, checking isWriteLocked before and after
35 */
36 void releaseWriteLock(StampedLock lock, long stamp) {
37 assertTrue(lock.isWriteLocked());
38 assertValid(lock, stamp);
39 lock.unlockWrite(stamp);
40 assertFalse(lock.isWriteLocked());
41 assertFalse(lock.validate(stamp));
42 }
43
44 /**
45 * Releases read lock, checking isReadLocked before and after
46 */
47 void releaseReadLock(StampedLock lock, long stamp) {
48 assertTrue(lock.isReadLocked());
49 assertValid(lock, stamp);
50 lock.unlockRead(stamp);
51 assertFalse(lock.isReadLocked());
52 assertTrue(lock.validate(stamp));
53 }
54
55 long assertNonZero(long v) {
56 assertTrue(v != 0L);
57 return v;
58 }
59
60 long assertValid(StampedLock lock, long stamp) {
61 assertTrue(stamp != 0L);
62 assertTrue(lock.validate(stamp));
63 return stamp;
64 }
65
66 void assertUnlocked(StampedLock lock) {
67 assertFalse(lock.isReadLocked());
68 assertFalse(lock.isWriteLocked());
69 assertEquals(0, lock.getReadLockCount());
70 assertValid(lock, lock.tryOptimisticRead());
71 }
72
73 List<Action> lockLockers(Lock lock) {
74 List<Action> lockers = new ArrayList<>();
75 lockers.add(() -> lock.lock());
76 lockers.add(() -> lock.lockInterruptibly());
77 lockers.add(() -> lock.tryLock());
78 lockers.add(() -> lock.tryLock(Long.MIN_VALUE, DAYS));
79 lockers.add(() -> lock.tryLock(0L, DAYS));
80 lockers.add(() -> lock.tryLock(Long.MAX_VALUE, DAYS));
81 return lockers;
82 }
83
84 List<Function<StampedLock, Long>> readLockers() {
85 List<Function<StampedLock, Long>> readLockers = new ArrayList<>();
86 readLockers.add(sl -> sl.readLock());
87 readLockers.add(sl -> sl.tryReadLock());
88 readLockers.add(sl -> readLockInterruptiblyUninterrupted(sl));
89 readLockers.add(sl -> tryReadLockUninterrupted(sl, Long.MIN_VALUE, DAYS));
90 readLockers.add(sl -> tryReadLockUninterrupted(sl, 0L, DAYS));
91 readLockers.add(sl -> sl.tryConvertToReadLock(sl.tryOptimisticRead()));
92 return readLockers;
93 }
94
95 List<BiConsumer<StampedLock, Long>> readUnlockers() {
96 List<BiConsumer<StampedLock, Long>> readUnlockers = new ArrayList<>();
97 readUnlockers.add((sl, stamp) -> sl.unlockRead(stamp));
98 readUnlockers.add((sl, stamp) -> assertTrue(sl.tryUnlockRead()));
99 readUnlockers.add((sl, stamp) -> sl.asReadLock().unlock());
100 readUnlockers.add((sl, stamp) -> sl.unlock(stamp));
101 readUnlockers.add((sl, stamp) -> assertValid(sl, sl.tryConvertToOptimisticRead(stamp)));
102 return readUnlockers;
103 }
104
105 List<Function<StampedLock, Long>> writeLockers() {
106 List<Function<StampedLock, Long>> writeLockers = new ArrayList<>();
107 writeLockers.add(sl -> sl.writeLock());
108 writeLockers.add(sl -> sl.tryWriteLock());
109 writeLockers.add(sl -> writeLockInterruptiblyUninterrupted(sl));
110 writeLockers.add(sl -> tryWriteLockUninterrupted(sl, Long.MIN_VALUE, DAYS));
111 writeLockers.add(sl -> tryWriteLockUninterrupted(sl, 0L, DAYS));
112 writeLockers.add(sl -> sl.tryConvertToWriteLock(sl.tryOptimisticRead()));
113 return writeLockers;
114 }
115
116 List<BiConsumer<StampedLock, Long>> writeUnlockers() {
117 List<BiConsumer<StampedLock, Long>> writeUnlockers = new ArrayList<>();
118 writeUnlockers.add((sl, stamp) -> sl.unlockWrite(stamp));
119 writeUnlockers.add((sl, stamp) -> assertTrue(sl.tryUnlockWrite()));
120 writeUnlockers.add((sl, stamp) -> sl.asWriteLock().unlock());
121 writeUnlockers.add((sl, stamp) -> sl.unlock(stamp));
122 writeUnlockers.add((sl, stamp) -> assertValid(sl, sl.tryConvertToOptimisticRead(stamp)));
123 return writeUnlockers;
124 }
125
126 /**
127 * Constructed StampedLock is in unlocked state
128 */
129 public void testConstructor() {
130 assertUnlocked(new StampedLock());
131 }
132
133 /**
134 * write-locking, then unlocking, an unlocked lock succeed
135 */
136 public void testWriteLock_lockUnlock() {
137 StampedLock lock = new StampedLock();
138
139 for (Function<StampedLock, Long> writeLocker : writeLockers())
140 for (BiConsumer<StampedLock, Long> writeUnlocker : writeUnlockers()) {
141 assertFalse(lock.isWriteLocked());
142 assertFalse(lock.isReadLocked());
143 assertEquals(0, lock.getReadLockCount());
144
145 long s = writeLocker.apply(lock);
146 assertValid(lock, s);
147 assertTrue(lock.isWriteLocked());
148 assertFalse(lock.isReadLocked());
149 assertEquals(0, lock.getReadLockCount());
150 writeUnlocker.accept(lock, s);
151 assertUnlocked(lock);
152 }
153 }
154
155 /**
156 * read-locking, then unlocking, an unlocked lock succeed
157 */
158 public void testReadLock_lockUnlock() {
159 StampedLock lock = new StampedLock();
160
161 for (Function<StampedLock, Long> readLocker : readLockers())
162 for (BiConsumer<StampedLock, Long> readUnlocker : readUnlockers()) {
163 long s = 42;
164 for (int i = 0; i < 2; i++) {
165 s = assertValid(lock, readLocker.apply(lock));
166 assertFalse(lock.isWriteLocked());
167 assertTrue(lock.isReadLocked());
168 assertEquals(i + 1, lock.getReadLockCount());
169 }
170 for (int i = 0; i < 2; i++) {
171 assertFalse(lock.isWriteLocked());
172 assertTrue(lock.isReadLocked());
173 assertEquals(2 - i, lock.getReadLockCount());
174 readUnlocker.accept(lock, s);
175 }
176 assertUnlocked(lock);
177 }
178 }
179
180 /**
181 * tryUnlockWrite fails if not write locked
182 */
183 public void testTryUnlockWrite_failure() {
184 StampedLock lock = new StampedLock();
185 assertFalse(lock.tryUnlockWrite());
186
187 for (Function<StampedLock, Long> readLocker : readLockers())
188 for (BiConsumer<StampedLock, Long> readUnlocker : readUnlockers()) {
189 long s = assertValid(lock, readLocker.apply(lock));
190 assertFalse(lock.tryUnlockWrite());
191 assertTrue(lock.isReadLocked());
192 readUnlocker.accept(lock, s);
193 assertUnlocked(lock);
194 }
195 }
196
197 /**
198 * tryUnlockRead fails if not read locked
199 */
200 public void testTryUnlockRead_failure() {
201 StampedLock lock = new StampedLock();
202 assertFalse(lock.tryUnlockRead());
203
204 for (Function<StampedLock, Long> writeLocker : writeLockers())
205 for (BiConsumer<StampedLock, Long> writeUnlocker : writeUnlockers()) {
206 long s = writeLocker.apply(lock);
207 assertFalse(lock.tryUnlockRead());
208 assertTrue(lock.isWriteLocked());
209 writeUnlocker.accept(lock, s);
210 assertUnlocked(lock);
211 }
212 }
213
214 /**
215 * validate(0L) fails
216 */
217 public void testValidate0() {
218 StampedLock lock = new StampedLock();
219 assertFalse(lock.validate(0L));
220 }
221
222 /**
223 * A stamp obtained from a successful lock operation validates while the lock is held
224 */
225 public void testValidate() throws InterruptedException {
226 StampedLock lock = new StampedLock();
227
228 for (Function<StampedLock, Long> readLocker : readLockers())
229 for (BiConsumer<StampedLock, Long> readUnlocker : readUnlockers()) {
230 long s = assertNonZero(readLocker.apply(lock));
231 assertTrue(lock.validate(s));
232 readUnlocker.accept(lock, s);
233 }
234
235 for (Function<StampedLock, Long> writeLocker : writeLockers())
236 for (BiConsumer<StampedLock, Long> writeUnlocker : writeUnlockers()) {
237 long s = assertNonZero(writeLocker.apply(lock));
238 assertTrue(lock.validate(s));
239 writeUnlocker.accept(lock, s);
240 }
241 }
242
243 /**
244 * A stamp obtained from an unsuccessful lock operation does not validate
245 */
246 public void testValidate2() throws InterruptedException {
247 StampedLock lock = new StampedLock();
248 long s = assertNonZero(lock.writeLock());
249 assertTrue(lock.validate(s));
250 assertFalse(lock.validate(lock.tryWriteLock()));
251 assertFalse(lock.validate(lock.tryWriteLock(0L, SECONDS)));
252 assertFalse(lock.validate(lock.tryReadLock()));
253 assertFalse(lock.validate(lock.tryReadLock(0L, SECONDS)));
254 assertFalse(lock.validate(lock.tryOptimisticRead()));
255 lock.unlockWrite(s);
256 }
257
258 void assertThrowInterruptedExceptionWhenPreInterrupted(Action[] actions) {
259 for (Action action : actions) {
260 Thread.currentThread().interrupt();
261 try {
262 action.run();
263 shouldThrow();
264 }
265 catch (InterruptedException success) {}
266 catch (Throwable fail) { threadUnexpectedException(fail); }
267 assertFalse(Thread.interrupted());
268 }
269 }
270
271 /**
272 * interruptible operations throw InterruptedException when pre-interrupted
273 */
274 public void testInterruptibleOperationsThrowInterruptedExceptionWhenPreInterrupted() {
275 final StampedLock lock = new StampedLock();
276
277 Action[] interruptibleLockActions = {
278 () -> lock.writeLockInterruptibly(),
279 () -> lock.tryWriteLock(Long.MIN_VALUE, DAYS),
280 () -> lock.tryWriteLock(Long.MAX_VALUE, DAYS),
281 () -> lock.readLockInterruptibly(),
282 () -> lock.tryReadLock(Long.MIN_VALUE, DAYS),
283 () -> lock.tryReadLock(Long.MAX_VALUE, DAYS),
284 () -> lock.asWriteLock().lockInterruptibly(),
285 () -> lock.asWriteLock().tryLock(0L, DAYS),
286 () -> lock.asWriteLock().tryLock(Long.MAX_VALUE, DAYS),
287 () -> lock.asReadLock().lockInterruptibly(),
288 () -> lock.asReadLock().tryLock(0L, DAYS),
289 () -> lock.asReadLock().tryLock(Long.MAX_VALUE, DAYS),
290 };
291 shuffle(interruptibleLockActions);
292
293 assertThrowInterruptedExceptionWhenPreInterrupted(interruptibleLockActions);
294 {
295 long s = lock.writeLock();
296 assertThrowInterruptedExceptionWhenPreInterrupted(interruptibleLockActions);
297 lock.unlockWrite(s);
298 }
299 {
300 long s = lock.readLock();
301 assertThrowInterruptedExceptionWhenPreInterrupted(interruptibleLockActions);
302 lock.unlockRead(s);
303 }
304 }
305
306 void assertThrowInterruptedExceptionWhenInterrupted(Action[] actions) {
307 int n = actions.length;
308 Future<?>[] futures = new Future<?>[n];
309 CountDownLatch threadsStarted = new CountDownLatch(n);
310 CountDownLatch done = new CountDownLatch(n);
311
312 for (int i = 0; i < n; i++) {
313 Action action = actions[i];
314 futures[i] = cachedThreadPool.submit(new CheckedRunnable() {
315 public void realRun() throws Throwable {
316 threadsStarted.countDown();
317 try {
318 action.run();
319 shouldThrow();
320 }
321 catch (InterruptedException success) {}
322 catch (Throwable fail) { threadUnexpectedException(fail); }
323 assertFalse(Thread.interrupted());
324 done.countDown();
325 }});
326 }
327
328 await(threadsStarted);
329 assertEquals(n, done.getCount());
330 for (Future<?> future : futures) // Interrupt all the tasks
331 future.cancel(true);
332 await(done);
333 }
334
335 /**
336 * interruptible operations throw InterruptedException when write locked and interrupted
337 */
338 public void testInterruptibleOperationsThrowInterruptedExceptionWriteLockedInterrupted() {
339 final StampedLock lock = new StampedLock();
340 long s = lock.writeLock();
341
342 Action[] interruptibleLockBlockingActions = {
343 () -> lock.writeLockInterruptibly(),
344 () -> lock.tryWriteLock(Long.MAX_VALUE, DAYS),
345 () -> lock.readLockInterruptibly(),
346 () -> lock.tryReadLock(Long.MAX_VALUE, DAYS),
347 () -> lock.asWriteLock().lockInterruptibly(),
348 () -> lock.asWriteLock().tryLock(Long.MAX_VALUE, DAYS),
349 () -> lock.asReadLock().lockInterruptibly(),
350 () -> lock.asReadLock().tryLock(Long.MAX_VALUE, DAYS),
351 };
352 shuffle(interruptibleLockBlockingActions);
353
354 assertThrowInterruptedExceptionWhenInterrupted(interruptibleLockBlockingActions);
355 }
356
357 /**
358 * interruptible operations throw InterruptedException when read locked and interrupted
359 */
360 public void testInterruptibleOperationsThrowInterruptedExceptionReadLockedInterrupted() {
361 final StampedLock lock = new StampedLock();
362 long s = lock.readLock();
363
364 Action[] interruptibleLockBlockingActions = {
365 () -> lock.writeLockInterruptibly(),
366 () -> lock.tryWriteLock(Long.MAX_VALUE, DAYS),
367 () -> lock.asWriteLock().lockInterruptibly(),
368 () -> lock.asWriteLock().tryLock(Long.MAX_VALUE, DAYS),
369 };
370 shuffle(interruptibleLockBlockingActions);
371
372 assertThrowInterruptedExceptionWhenInterrupted(interruptibleLockBlockingActions);
373 }
374
375 /**
376 * Non-interruptible operations ignore and preserve interrupt status
377 */
378 public void testNonInterruptibleOperationsIgnoreInterrupts() {
379 final StampedLock lock = new StampedLock();
380 Thread.currentThread().interrupt();
381
382 for (BiConsumer<StampedLock, Long> readUnlocker : readUnlockers()) {
383 long s = assertValid(lock, lock.readLock());
384 readUnlocker.accept(lock, s);
385 s = assertValid(lock, lock.tryReadLock());
386 readUnlocker.accept(lock, s);
387 }
388
389 lock.asReadLock().lock();
390 lock.asReadLock().unlock();
391
392 for (BiConsumer<StampedLock, Long> writeUnlocker : writeUnlockers()) {
393 long s = assertValid(lock, lock.writeLock());
394 writeUnlocker.accept(lock, s);
395 s = assertValid(lock, lock.tryWriteLock());
396 writeUnlocker.accept(lock, s);
397 }
398
399 lock.asWriteLock().lock();
400 lock.asWriteLock().unlock();
401
402 assertTrue(Thread.interrupted());
403 }
404
405 /**
406 * tryWriteLock on an unlocked lock succeeds
407 */
408 public void testTryWriteLock() {
409 final StampedLock lock = new StampedLock();
410 long s = lock.tryWriteLock();
411 assertTrue(s != 0L);
412 assertTrue(lock.isWriteLocked());
413 assertEquals(0L, lock.tryWriteLock());
414 releaseWriteLock(lock, s);
415 }
416
417 /**
418 * tryWriteLock fails if locked
419 */
420 public void testTryWriteLockWhenLocked() {
421 final StampedLock lock = new StampedLock();
422 long s = lock.writeLock();
423 Thread t = newStartedThread(new CheckedRunnable() {
424 public void realRun() {
425 assertEquals(0L, lock.tryWriteLock());
426 }});
427
428 assertEquals(0L, lock.tryWriteLock());
429 awaitTermination(t);
430 releaseWriteLock(lock, s);
431 }
432
433 /**
434 * tryReadLock fails if write-locked
435 */
436 public void testTryReadLockWhenLocked() {
437 final StampedLock lock = new StampedLock();
438 long s = lock.writeLock();
439 Thread t = newStartedThread(new CheckedRunnable() {
440 public void realRun() {
441 assertEquals(0L, lock.tryReadLock());
442 }});
443
444 assertEquals(0L, lock.tryReadLock());
445 awaitTermination(t);
446 releaseWriteLock(lock, s);
447 }
448
449 /**
450 * Multiple threads can hold a read lock when not write-locked
451 */
452 public void testMultipleReadLocks() {
453 final StampedLock lock = new StampedLock();
454 final long s = lock.readLock();
455 Thread t = newStartedThread(new CheckedRunnable() {
456 public void realRun() throws InterruptedException {
457 long s2 = lock.tryReadLock();
458 assertValid(lock, s2);
459 lock.unlockRead(s2);
460 long s3 = lock.tryReadLock(LONG_DELAY_MS, MILLISECONDS);
461 assertValid(lock, s3);
462 lock.unlockRead(s3);
463 long s4 = lock.readLock();
464 assertValid(lock, s4);
465 lock.unlockRead(s4);
466 lock.asReadLock().lock();
467 lock.asReadLock().unlock();
468 lock.asReadLock().lockInterruptibly();
469 lock.asReadLock().unlock();
470 lock.asReadLock().tryLock(Long.MIN_VALUE, DAYS);
471 lock.asReadLock().unlock();
472 }});
473
474 awaitTermination(t);
475 lock.unlockRead(s);
476 }
477
478 /**
479 * A writelock succeeds only after a reading thread unlocks
480 */
481 public void testWriteAfterReadLock() throws InterruptedException {
482 final CountDownLatch threadStarted = new CountDownLatch(1);
483 final StampedLock lock = new StampedLock();
484 long rs = lock.readLock();
485 Thread t = newStartedThread(new CheckedRunnable() {
486 public void realRun() {
487 threadStarted.countDown();
488 long s = lock.writeLock();
489 lock.unlockWrite(s);
490 }});
491
492 threadStarted.await();
493 waitForThreadToEnterWaitState(t, MEDIUM_DELAY_MS);
494 assertFalse(lock.isWriteLocked());
495 lock.unlockRead(rs);
496 awaitTermination(t);
497 assertFalse(lock.isWriteLocked());
498 }
499
500 /**
501 * A writelock succeeds only after reading threads unlock
502 */
503 public void testWriteAfterMultipleReadLocks() {
504 final StampedLock lock = new StampedLock();
505 long s = lock.readLock();
506 Thread t1 = newStartedThread(new CheckedRunnable() {
507 public void realRun() {
508 long rs = lock.readLock();
509 lock.unlockRead(rs);
510 }});
511
512 awaitTermination(t1);
513
514 Thread t2 = newStartedThread(new CheckedRunnable() {
515 public void realRun() {
516 long ws = lock.writeLock();
517 lock.unlockWrite(ws);
518 }});
519
520 assertTrue(lock.isReadLocked());
521 assertFalse(lock.isWriteLocked());
522 lock.unlockRead(s);
523 awaitTermination(t2);
524 assertFalse(lock.isWriteLocked());
525 }
526
527 /**
528 * Readlocks succeed only after a writing thread unlocks
529 */
530 public void testReadAfterWriteLock() {
531 final StampedLock lock = new StampedLock();
532 final CountDownLatch threadsStarted = new CountDownLatch(2);
533 final long s = lock.writeLock();
534 Thread t1 = newStartedThread(new CheckedRunnable() {
535 public void realRun() {
536 threadsStarted.countDown();
537 long rs = lock.readLock();
538 lock.unlockRead(rs);
539 }});
540 Thread t2 = newStartedThread(new CheckedRunnable() {
541 public void realRun() {
542 threadsStarted.countDown();
543 long rs = lock.readLock();
544 lock.unlockRead(rs);
545 }});
546
547 await(threadsStarted);
548 waitForThreadToEnterWaitState(t1, MEDIUM_DELAY_MS);
549 waitForThreadToEnterWaitState(t2, MEDIUM_DELAY_MS);
550 releaseWriteLock(lock, s);
551 awaitTermination(t1);
552 awaitTermination(t2);
553 }
554
555 /**
556 * tryReadLock succeeds if read locked but not write locked
557 */
558 public void testTryLockWhenReadLocked() {
559 final StampedLock lock = new StampedLock();
560 long s = lock.readLock();
561 Thread t = newStartedThread(new CheckedRunnable() {
562 public void realRun() {
563 long rs = lock.tryReadLock();
564 assertValid(lock, rs);
565 lock.unlockRead(rs);
566 }});
567
568 awaitTermination(t);
569 lock.unlockRead(s);
570 }
571
572 /**
573 * tryWriteLock fails when read locked
574 */
575 public void testTryWriteLockWhenReadLocked() {
576 final StampedLock lock = new StampedLock();
577 long s = lock.readLock();
578 Thread t = newStartedThread(new CheckedRunnable() {
579 public void realRun() {
580 threadAssertEquals(0L, lock.tryWriteLock());
581 }});
582
583 awaitTermination(t);
584 lock.unlockRead(s);
585 }
586
587 /**
588 * timed lock operations time out if lock not available
589 */
590 public void testTimedLock_Timeout() throws Exception {
591 ArrayList<Future<?>> futures = new ArrayList<>();
592
593 // Write locked
594 final StampedLock lock = new StampedLock();
595 long stamp = lock.writeLock();
596 assertEquals(0L, lock.tryReadLock(0L, DAYS));
597 assertEquals(0L, lock.tryReadLock(Long.MIN_VALUE, DAYS));
598 assertFalse(lock.asReadLock().tryLock(0L, DAYS));
599 assertFalse(lock.asReadLock().tryLock(Long.MIN_VALUE, DAYS));
600 assertEquals(0L, lock.tryWriteLock(0L, DAYS));
601 assertEquals(0L, lock.tryWriteLock(Long.MIN_VALUE, DAYS));
602 assertFalse(lock.asWriteLock().tryLock(0L, DAYS));
603 assertFalse(lock.asWriteLock().tryLock(Long.MIN_VALUE, DAYS));
604
605 futures.add(cachedThreadPool.submit(new CheckedRunnable() {
606 public void realRun() throws InterruptedException {
607 long startTime = System.nanoTime();
608 assertEquals(0L, lock.tryWriteLock(timeoutMillis(), MILLISECONDS));
609 assertTrue(millisElapsedSince(startTime) >= timeoutMillis());
610 }}));
611
612 futures.add(cachedThreadPool.submit(new CheckedRunnable() {
613 public void realRun() throws InterruptedException {
614 long startTime = System.nanoTime();
615 assertEquals(0L, lock.tryReadLock(timeoutMillis(), MILLISECONDS));
616 assertTrue(millisElapsedSince(startTime) >= timeoutMillis());
617 }}));
618
619 // Read locked
620 final StampedLock lock2 = new StampedLock();
621 long stamp2 = lock2.readLock();
622 assertEquals(0L, lock2.tryWriteLock(0L, DAYS));
623 assertEquals(0L, lock2.tryWriteLock(Long.MIN_VALUE, DAYS));
624 assertFalse(lock2.asWriteLock().tryLock(0L, DAYS));
625 assertFalse(lock2.asWriteLock().tryLock(Long.MIN_VALUE, DAYS));
626
627 futures.add(cachedThreadPool.submit(new CheckedRunnable() {
628 public void realRun() throws InterruptedException {
629 long startTime = System.nanoTime();
630 assertEquals(0L, lock2.tryWriteLock(timeoutMillis(), MILLISECONDS));
631 assertTrue(millisElapsedSince(startTime) >= timeoutMillis());
632 }}));
633
634 for (Future<?> future : futures)
635 assertNull(future.get());
636
637 releaseWriteLock(lock, stamp);
638 releaseReadLock(lock2, stamp2);
639 }
640
641 /**
642 * writeLockInterruptibly succeeds if unlocked
643 */
644 public void testWriteLockInterruptibly() throws InterruptedException {
645 final StampedLock lock = new StampedLock();
646 long s = lock.writeLockInterruptibly();
647 assertTrue(lock.isWriteLocked());
648 releaseWriteLock(lock, s);
649 }
650
651 /**
652 * readLockInterruptibly succeeds if lock free
653 */
654 public void testReadLockInterruptibly() throws InterruptedException {
655 final StampedLock lock = new StampedLock();
656
657 long s = assertValid(lock, lock.readLockInterruptibly());
658 assertTrue(lock.isReadLocked());
659 lock.unlockRead(s);
660
661 lock.asReadLock().lockInterruptibly();
662 assertTrue(lock.isReadLocked());
663 lock.asReadLock().unlock();
664 }
665
666 /**
667 * A serialized lock deserializes as unlocked
668 */
669 public void testSerialization() {
670 StampedLock lock = new StampedLock();
671 lock.writeLock();
672 StampedLock clone = serialClone(lock);
673 assertTrue(lock.isWriteLocked());
674 assertFalse(clone.isWriteLocked());
675 long s = clone.writeLock();
676 assertTrue(clone.isWriteLocked());
677 clone.unlockWrite(s);
678 assertFalse(clone.isWriteLocked());
679 }
680
681 /**
682 * toString indicates current lock state
683 */
684 public void testToString() {
685 StampedLock lock = new StampedLock();
686 assertTrue(lock.toString().contains("Unlocked"));
687 long s = lock.writeLock();
688 assertTrue(lock.toString().contains("Write-locked"));
689 lock.unlockWrite(s);
690 s = lock.readLock();
691 assertTrue(lock.toString().contains("Read-locks"));
692 }
693
694 /**
695 * tryOptimisticRead succeeds and validates if unlocked, fails if
696 * exclusively locked
697 */
698 public void testValidateOptimistic() throws InterruptedException {
699 StampedLock lock = new StampedLock();
700
701 assertValid(lock, lock.tryOptimisticRead());
702
703 for (Function<StampedLock, Long> writeLocker : writeLockers()) {
704 long s = assertValid(lock, writeLocker.apply(lock));
705 assertEquals(0L, lock.tryOptimisticRead());
706 releaseWriteLock(lock, s);
707 }
708
709 for (Function<StampedLock, Long> readLocker : readLockers()) {
710 long s = assertValid(lock, readLocker.apply(lock));
711 long p = assertValid(lock, lock.tryOptimisticRead());
712 releaseReadLock(lock, s);
713 assertTrue(lock.validate(p));
714 }
715
716 assertValid(lock, lock.tryOptimisticRead());
717 }
718
719 /**
720 * tryOptimisticRead stamp does not validate if a write lock intervenes
721 */
722 public void testValidateOptimisticWriteLocked() {
723 final StampedLock lock = new StampedLock();
724 final long p = assertValid(lock, lock.tryOptimisticRead());
725 final long s = assertValid(lock, lock.writeLock());
726 assertFalse(lock.validate(p));
727 assertEquals(0L, lock.tryOptimisticRead());
728 assertTrue(lock.validate(s));
729 lock.unlockWrite(s);
730 }
731
732 /**
733 * tryOptimisticRead stamp does not validate if a write lock
734 * intervenes in another thread
735 */
736 public void testValidateOptimisticWriteLocked2()
737 throws InterruptedException {
738 final CountDownLatch running = new CountDownLatch(1);
739 final StampedLock lock = new StampedLock();
740 final long p = assertValid(lock, lock.tryOptimisticRead());
741
742 Thread t = newStartedThread(new CheckedInterruptedRunnable() {
743 public void realRun() throws InterruptedException {
744 lock.writeLockInterruptibly();
745 running.countDown();
746 lock.writeLockInterruptibly();
747 }});
748
749 running.await();
750 assertFalse(lock.validate(p));
751 assertEquals(0L, lock.tryOptimisticRead());
752 t.interrupt();
753 awaitTermination(t);
754 }
755
756 /**
757 * tryConvertToOptimisticRead succeeds and validates if successfully locked
758 */
759 public void testTryConvertToOptimisticRead() throws InterruptedException {
760 StampedLock lock = new StampedLock();
761 long s, p, q;
762 assertEquals(0L, lock.tryConvertToOptimisticRead(0L));
763
764 s = assertValid(lock, lock.tryOptimisticRead());
765 assertEquals(s, lock.tryConvertToOptimisticRead(s));
766 assertTrue(lock.validate(s));
767
768 for (Function<StampedLock, Long> writeLocker : writeLockers()) {
769 s = assertValid(lock, writeLocker.apply(lock));
770 p = assertValid(lock, lock.tryConvertToOptimisticRead(s));
771 assertFalse(lock.validate(s));
772 assertTrue(lock.validate(p));
773 assertUnlocked(lock);
774 }
775
776 for (Function<StampedLock, Long> readLocker : readLockers()) {
777 s = assertValid(lock, readLocker.apply(lock));
778 q = assertValid(lock, lock.tryOptimisticRead());
779 assertEquals(q, lock.tryConvertToOptimisticRead(q));
780 assertTrue(lock.validate(q));
781 assertTrue(lock.isReadLocked());
782 p = assertValid(lock, lock.tryConvertToOptimisticRead(s));
783 assertTrue(lock.validate(p));
784 assertTrue(lock.validate(s));
785 assertUnlocked(lock);
786 assertEquals(q, lock.tryConvertToOptimisticRead(q));
787 assertTrue(lock.validate(q));
788 }
789 }
790
791 /**
792 * tryConvertToReadLock succeeds for valid stamps
793 */
794 public void testTryConvertToReadLock() throws InterruptedException {
795 StampedLock lock = new StampedLock();
796 long s, p;
797
798 assertEquals(0L, lock.tryConvertToReadLock(0L));
799
800 s = assertValid(lock, lock.tryOptimisticRead());
801 p = assertValid(lock, lock.tryConvertToReadLock(s));
802 assertTrue(lock.isReadLocked());
803 assertEquals(1, lock.getReadLockCount());
804 assertTrue(lock.validate(s));
805 lock.unlockRead(p);
806
807 s = assertValid(lock, lock.tryOptimisticRead());
808 lock.readLock();
809 p = assertValid(lock, lock.tryConvertToReadLock(s));
810 assertTrue(lock.isReadLocked());
811 assertEquals(2, lock.getReadLockCount());
812 lock.unlockRead(p);
813 lock.unlockRead(p);
814 assertUnlocked(lock);
815
816 for (BiConsumer<StampedLock, Long> readUnlocker : readUnlockers()) {
817 for (Function<StampedLock, Long> writeLocker : writeLockers()) {
818 s = assertValid(lock, writeLocker.apply(lock));
819 p = assertValid(lock, lock.tryConvertToReadLock(s));
820 assertFalse(lock.validate(s));
821 assertTrue(lock.isReadLocked());
822 assertEquals(1, lock.getReadLockCount());
823 readUnlocker.accept(lock, p);
824 }
825
826 for (Function<StampedLock, Long> readLocker : readLockers()) {
827 s = assertValid(lock, readLocker.apply(lock));
828 assertEquals(s, lock.tryConvertToReadLock(s));
829 assertTrue(lock.validate(s));
830 assertTrue(lock.isReadLocked());
831 assertEquals(1, lock.getReadLockCount());
832 readUnlocker.accept(lock, s);
833 }
834 }
835 }
836
837 /**
838 * tryConvertToWriteLock succeeds if lock available; fails if multiply read locked
839 */
840 public void testTryConvertToWriteLock() throws InterruptedException {
841 StampedLock lock = new StampedLock();
842 long s, p;
843
844 assertEquals(0L, lock.tryConvertToWriteLock(0L));
845
846 assertTrue((s = lock.tryOptimisticRead()) != 0L);
847 assertTrue((p = lock.tryConvertToWriteLock(s)) != 0L);
848 assertTrue(lock.isWriteLocked());
849 lock.unlockWrite(p);
850
851 for (BiConsumer<StampedLock, Long> writeUnlocker : writeUnlockers()) {
852 for (Function<StampedLock, Long> writeLocker : writeLockers()) {
853 s = assertValid(lock, writeLocker.apply(lock));
854 assertEquals(s, lock.tryConvertToWriteLock(s));
855 assertTrue(lock.validate(s));
856 assertTrue(lock.isWriteLocked());
857 writeUnlocker.accept(lock, s);
858 }
859
860 for (Function<StampedLock, Long> readLocker : readLockers()) {
861 s = assertValid(lock, readLocker.apply(lock));
862 p = assertValid(lock, lock.tryConvertToWriteLock(s));
863 assertFalse(lock.validate(s));
864 assertTrue(lock.validate(p));
865 assertTrue(lock.isWriteLocked());
866 writeUnlocker.accept(lock, p);
867 }
868 }
869
870 // failure if multiply read locked
871 for (Function<StampedLock, Long> readLocker : readLockers()) {
872 s = assertValid(lock, readLocker.apply(lock));
873 p = assertValid(lock, readLocker.apply(lock));
874 assertEquals(0L, lock.tryConvertToWriteLock(s));
875 assertTrue(lock.validate(s));
876 assertTrue(lock.validate(p));
877 assertEquals(2, lock.getReadLockCount());
878 lock.unlock(p);
879 lock.unlock(s);
880 assertUnlocked(lock);
881 }
882 }
883
884 /**
885 * asWriteLock can be locked and unlocked
886 */
887 public void testAsWriteLock() throws Throwable {
888 StampedLock sl = new StampedLock();
889 Lock lock = sl.asWriteLock();
890 for (Action locker : lockLockers(lock)) {
891 locker.run();
892 assertTrue(sl.isWriteLocked());
893 assertFalse(sl.isReadLocked());
894 assertFalse(lock.tryLock());
895 lock.unlock();
896 assertUnlocked(sl);
897 }
898 }
899
900 /**
901 * asReadLock can be locked and unlocked
902 */
903 public void testAsReadLock() throws Throwable {
904 StampedLock sl = new StampedLock();
905 Lock lock = sl.asReadLock();
906 for (Action locker : lockLockers(lock)) {
907 locker.run();
908 assertTrue(sl.isReadLocked());
909 assertFalse(sl.isWriteLocked());
910 assertEquals(1, sl.getReadLockCount());
911 locker.run();
912 assertTrue(sl.isReadLocked());
913 assertEquals(2, sl.getReadLockCount());
914 lock.unlock();
915 lock.unlock();
916 assertUnlocked(sl);
917 }
918 }
919
920 /**
921 * asReadWriteLock.writeLock can be locked and unlocked
922 */
923 public void testAsReadWriteLockWriteLock() throws Throwable {
924 StampedLock sl = new StampedLock();
925 Lock lock = sl.asReadWriteLock().writeLock();
926 for (Action locker : lockLockers(lock)) {
927 locker.run();
928 assertTrue(sl.isWriteLocked());
929 assertFalse(sl.isReadLocked());
930 assertFalse(lock.tryLock());
931 lock.unlock();
932 assertUnlocked(sl);
933 }
934 }
935
936 /**
937 * asReadWriteLock.readLock can be locked and unlocked
938 */
939 public void testAsReadWriteLockReadLock() throws Throwable {
940 StampedLock sl = new StampedLock();
941 Lock lock = sl.asReadWriteLock().readLock();
942 for (Action locker : lockLockers(lock)) {
943 locker.run();
944 assertTrue(sl.isReadLocked());
945 assertFalse(sl.isWriteLocked());
946 assertEquals(1, sl.getReadLockCount());
947 locker.run();
948 assertTrue(sl.isReadLocked());
949 assertEquals(2, sl.getReadLockCount());
950 lock.unlock();
951 lock.unlock();
952 assertUnlocked(sl);
953 }
954 }
955
956 /**
957 * Lock.newCondition throws UnsupportedOperationException
958 */
959 public void testLockViewsDoNotSupportConditions() {
960 StampedLock sl = new StampedLock();
961 assertThrows(UnsupportedOperationException.class,
962 () -> sl.asWriteLock().newCondition(),
963 () -> sl.asReadLock().newCondition(),
964 () -> sl.asReadWriteLock().writeLock().newCondition(),
965 () -> sl.asReadWriteLock().readLock().newCondition());
966 }
967
968 /**
969 * Passing optimistic read stamps to unlock operations result in
970 * IllegalMonitorStateException
971 */
972 public void testCannotUnlockOptimisticReadStamps() {
973 Runnable[] actions = {
974 () -> {
975 StampedLock sl = new StampedLock();
976 long stamp = assertValid(sl, sl.tryOptimisticRead());
977 sl.unlockRead(stamp);
978 },
979 () -> {
980 StampedLock sl = new StampedLock();
981 long stamp = sl.tryOptimisticRead();
982 sl.unlock(stamp);
983 },
984
985 () -> {
986 StampedLock sl = new StampedLock();
987 long stamp = sl.tryOptimisticRead();
988 sl.writeLock();
989 sl.unlock(stamp);
990 },
991 () -> {
992 StampedLock sl = new StampedLock();
993 sl.readLock();
994 long stamp = assertValid(sl, sl.tryOptimisticRead());
995 sl.unlockRead(stamp);
996 },
997 () -> {
998 StampedLock sl = new StampedLock();
999 sl.readLock();
1000 long stamp = assertValid(sl, sl.tryOptimisticRead());
1001 sl.unlock(stamp);
1002 },
1003
1004 () -> {
1005 StampedLock sl = new StampedLock();
1006 long stamp = sl.tryConvertToOptimisticRead(sl.writeLock());
1007 assertValid(sl, stamp);
1008 sl.writeLock();
1009 sl.unlockWrite(stamp);
1010 },
1011 () -> {
1012 StampedLock sl = new StampedLock();
1013 long stamp = sl.tryConvertToOptimisticRead(sl.writeLock());
1014 sl.writeLock();
1015 sl.unlock(stamp);
1016 },
1017 () -> {
1018 StampedLock sl = new StampedLock();
1019 long stamp = sl.tryConvertToOptimisticRead(sl.writeLock());
1020 sl.readLock();
1021 sl.unlockRead(stamp);
1022 },
1023 () -> {
1024 StampedLock sl = new StampedLock();
1025 long stamp = sl.tryConvertToOptimisticRead(sl.writeLock());
1026 sl.readLock();
1027 sl.unlock(stamp);
1028 },
1029
1030 () -> {
1031 StampedLock sl = new StampedLock();
1032 long stamp = sl.tryConvertToOptimisticRead(sl.readLock());
1033 assertValid(sl, stamp);
1034 sl.writeLock();
1035 sl.unlockWrite(stamp);
1036 },
1037 () -> {
1038 StampedLock sl = new StampedLock();
1039 long stamp = sl.tryConvertToOptimisticRead(sl.readLock());
1040 sl.writeLock();
1041 sl.unlock(stamp);
1042 },
1043 () -> {
1044 StampedLock sl = new StampedLock();
1045 long stamp = sl.tryConvertToOptimisticRead(sl.readLock());
1046 sl.readLock();
1047 sl.unlockRead(stamp);
1048 },
1049 () -> {
1050 StampedLock sl = new StampedLock();
1051 sl.readLock();
1052 long stamp = sl.tryConvertToOptimisticRead(sl.readLock());
1053 assertValid(sl, stamp);
1054 sl.readLock();
1055 sl.unlockRead(stamp);
1056 },
1057 () -> {
1058 StampedLock sl = new StampedLock();
1059 long stamp = sl.tryConvertToOptimisticRead(sl.readLock());
1060 sl.readLock();
1061 sl.unlock(stamp);
1062 },
1063 () -> {
1064 StampedLock sl = new StampedLock();
1065 sl.readLock();
1066 long stamp = sl.tryConvertToOptimisticRead(sl.readLock());
1067 sl.readLock();
1068 sl.unlock(stamp);
1069 },
1070 };
1071
1072 assertThrows(IllegalMonitorStateException.class, actions);
1073 }
1074
1075 static long writeLockInterruptiblyUninterrupted(StampedLock sl) {
1076 try { return sl.writeLockInterruptibly(); }
1077 catch (InterruptedException ex) { throw new AssertionError(ex); }
1078 }
1079
1080 static long tryWriteLockUninterrupted(StampedLock sl, long time, TimeUnit unit) {
1081 try { return sl.tryWriteLock(time, unit); }
1082 catch (InterruptedException ex) { throw new AssertionError(ex); }
1083 }
1084
1085 static long readLockInterruptiblyUninterrupted(StampedLock sl) {
1086 try { return sl.readLockInterruptibly(); }
1087 catch (InterruptedException ex) { throw new AssertionError(ex); }
1088 }
1089
1090 static long tryReadLockUninterrupted(StampedLock sl, long time, TimeUnit unit) {
1091 try { return sl.tryReadLock(time, unit); }
1092 catch (InterruptedException ex) { throw new AssertionError(ex); }
1093 }
1094
1095 /**
1096 * Invalid stamps result in IllegalMonitorStateException
1097 */
1098 public void testInvalidStampsThrowIllegalMonitorStateException() {
1099 final StampedLock sl = new StampedLock();
1100
1101 assertThrows(IllegalMonitorStateException.class,
1102 () -> sl.unlockWrite(0L),
1103 () -> sl.unlockRead(0L),
1104 () -> sl.unlock(0L));
1105
1106 final long optimisticStamp = sl.tryOptimisticRead();
1107 final long readStamp = sl.readLock();
1108 sl.unlockRead(readStamp);
1109 final long writeStamp = sl.writeLock();
1110 sl.unlockWrite(writeStamp);
1111 assertTrue(optimisticStamp != 0L && readStamp != 0L && writeStamp != 0L);
1112 final long[] noLongerValidStamps = { optimisticStamp, readStamp, writeStamp };
1113 final Runnable assertNoLongerValidStampsThrow = () -> {
1114 for (long noLongerValidStamp : noLongerValidStamps)
1115 assertThrows(IllegalMonitorStateException.class,
1116 () -> sl.unlockWrite(noLongerValidStamp),
1117 () -> sl.unlockRead(noLongerValidStamp),
1118 () -> sl.unlock(noLongerValidStamp));
1119 };
1120 assertNoLongerValidStampsThrow.run();
1121
1122 for (Function<StampedLock, Long> readLocker : readLockers())
1123 for (BiConsumer<StampedLock, Long> readUnlocker : readUnlockers()) {
1124 final long stamp = readLocker.apply(sl);
1125 assertValid(sl, stamp);
1126 assertNoLongerValidStampsThrow.run();
1127 assertThrows(IllegalMonitorStateException.class,
1128 () -> sl.unlockWrite(stamp),
1129 () -> sl.unlockRead(sl.tryOptimisticRead()),
1130 () -> sl.unlockRead(0L));
1131 readUnlocker.accept(sl, stamp);
1132 assertUnlocked(sl);
1133 assertNoLongerValidStampsThrow.run();
1134 }
1135
1136 for (Function<StampedLock, Long> writeLocker : writeLockers())
1137 for (BiConsumer<StampedLock, Long> writeUnlocker : writeUnlockers()) {
1138 final long stamp = writeLocker.apply(sl);
1139 assertValid(sl, stamp);
1140 assertNoLongerValidStampsThrow.run();
1141 assertThrows(IllegalMonitorStateException.class,
1142 () -> sl.unlockRead(stamp),
1143 () -> sl.unlockWrite(0L));
1144 writeUnlocker.accept(sl, stamp);
1145 assertUnlocked(sl);
1146 assertNoLongerValidStampsThrow.run();
1147 }
1148 }
1149
1150 /**
1151 * Read locks can be very deeply nested
1152 */
1153 public void testDeeplyNestedReadLocks() {
1154 final StampedLock lock = new StampedLock();
1155 final int depth = 300;
1156 final long[] stamps = new long[depth];
1157 final List<Function<StampedLock, Long>> readLockers = readLockers();
1158 final List<BiConsumer<StampedLock, Long>> readUnlockers = readUnlockers();
1159 for (int i = 0; i < depth; i++) {
1160 Function<StampedLock, Long> readLocker
1161 = readLockers.get(i % readLockers.size());
1162 long stamp = readLocker.apply(lock);
1163 assertEquals(i + 1, lock.getReadLockCount());
1164 assertTrue(lock.isReadLocked());
1165 stamps[i] = stamp;
1166 }
1167 for (int i = 0; i < depth; i++) {
1168 BiConsumer<StampedLock, Long> readUnlocker
1169 = readUnlockers.get(i % readUnlockers.size());
1170 assertEquals(depth - i, lock.getReadLockCount());
1171 assertTrue(lock.isReadLocked());
1172 readUnlocker.accept(lock, stamps[depth - 1 - i]);
1173 }
1174 assertUnlocked(lock);
1175 }
1176 }