ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/jsr166/jsr166/src/test/tck/StampedLockTest.java
Revision: 1.28
Committed: Wed Aug 24 22:22:39 2016 UTC (7 years, 8 months ago) by jsr166
Branch: MAIN
Changes since 1.27: +0 -1 lines
Log Message:
fix imports

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 CountDownLatch running = new CountDownLatch(1);
276 final StampedLock lock = new StampedLock();
277
278 Action[] interruptibleLockActions = {
279 () -> lock.writeLockInterruptibly(),
280 () -> lock.tryWriteLock(Long.MIN_VALUE, DAYS),
281 () -> lock.tryWriteLock(Long.MAX_VALUE, DAYS),
282 () -> lock.readLockInterruptibly(),
283 () -> lock.tryReadLock(Long.MIN_VALUE, DAYS),
284 () -> lock.tryReadLock(Long.MAX_VALUE, DAYS),
285 () -> lock.asWriteLock().lockInterruptibly(),
286 () -> lock.asWriteLock().tryLock(0L, DAYS),
287 () -> lock.asWriteLock().tryLock(Long.MAX_VALUE, DAYS),
288 () -> lock.asReadLock().lockInterruptibly(),
289 () -> lock.asReadLock().tryLock(0L, DAYS),
290 () -> lock.asReadLock().tryLock(Long.MAX_VALUE, DAYS),
291 };
292 shuffle(interruptibleLockActions);
293
294 assertThrowInterruptedExceptionWhenPreInterrupted(interruptibleLockActions);
295 {
296 long s = lock.writeLock();
297 assertThrowInterruptedExceptionWhenPreInterrupted(interruptibleLockActions);
298 lock.unlockWrite(s);
299 }
300 {
301 long s = lock.readLock();
302 assertThrowInterruptedExceptionWhenPreInterrupted(interruptibleLockActions);
303 lock.unlockRead(s);
304 }
305 }
306
307 void assertThrowInterruptedExceptionWhenInterrupted(Action[] actions) {
308 int n = actions.length;
309 Future<?>[] futures = new Future<?>[n];
310 CountDownLatch threadsStarted = new CountDownLatch(n);
311 CountDownLatch done = new CountDownLatch(n);
312
313 for (int i = 0; i < n; i++) {
314 Action action = actions[i];
315 futures[i] = cachedThreadPool.submit(new CheckedRunnable() {
316 public void realRun() throws Throwable {
317 threadsStarted.countDown();
318 try {
319 action.run();
320 shouldThrow();
321 }
322 catch (InterruptedException success) {}
323 catch (Throwable fail) { threadUnexpectedException(fail); }
324 assertFalse(Thread.interrupted());
325 done.countDown();
326 }});
327 }
328
329 await(threadsStarted);
330 assertEquals(n, done.getCount());
331 for (Future<?> future : futures) // Interrupt all the tasks
332 future.cancel(true);
333 await(done);
334 }
335
336 /**
337 * interruptible operations throw InterruptedException when write locked and interrupted
338 */
339 public void testInterruptibleOperationsThrowInterruptedExceptionWriteLockedInterrupted() {
340 final CountDownLatch running = new CountDownLatch(1);
341 final StampedLock lock = new StampedLock();
342 long s = lock.writeLock();
343
344 Action[] interruptibleLockBlockingActions = {
345 () -> lock.writeLockInterruptibly(),
346 () -> lock.tryWriteLock(Long.MAX_VALUE, DAYS),
347 () -> lock.readLockInterruptibly(),
348 () -> lock.tryReadLock(Long.MAX_VALUE, DAYS),
349 () -> lock.asWriteLock().lockInterruptibly(),
350 () -> lock.asWriteLock().tryLock(Long.MAX_VALUE, DAYS),
351 () -> lock.asReadLock().lockInterruptibly(),
352 () -> lock.asReadLock().tryLock(Long.MAX_VALUE, DAYS),
353 };
354 shuffle(interruptibleLockBlockingActions);
355
356 assertThrowInterruptedExceptionWhenInterrupted(interruptibleLockBlockingActions);
357 }
358
359 /**
360 * interruptible operations throw InterruptedException when read locked and interrupted
361 */
362 public void testInterruptibleOperationsThrowInterruptedExceptionReadLockedInterrupted() {
363 final CountDownLatch running = new CountDownLatch(1);
364 final StampedLock lock = new StampedLock();
365 long s = lock.readLock();
366
367 Action[] interruptibleLockBlockingActions = {
368 () -> lock.writeLockInterruptibly(),
369 () -> lock.tryWriteLock(Long.MAX_VALUE, DAYS),
370 () -> lock.asWriteLock().lockInterruptibly(),
371 () -> lock.asWriteLock().tryLock(Long.MAX_VALUE, DAYS),
372 };
373 shuffle(interruptibleLockBlockingActions);
374
375 assertThrowInterruptedExceptionWhenInterrupted(interruptibleLockBlockingActions);
376 }
377
378 /**
379 * Non-interruptible operations ignore and preserve interrupt status
380 */
381 public void testNonInterruptibleOperationsIgnoreInterrupts() {
382 final StampedLock lock = new StampedLock();
383 Thread.currentThread().interrupt();
384
385 for (BiConsumer<StampedLock, Long> readUnlocker : readUnlockers()) {
386 long s = assertValid(lock, lock.readLock());
387 readUnlocker.accept(lock, s);
388 s = assertValid(lock, lock.tryReadLock());
389 readUnlocker.accept(lock, s);
390 }
391
392 lock.asReadLock().lock();
393 lock.asReadLock().unlock();
394
395 for (BiConsumer<StampedLock, Long> writeUnlocker : writeUnlockers()) {
396 long s = assertValid(lock, lock.writeLock());
397 writeUnlocker.accept(lock, s);
398 s = assertValid(lock, lock.tryWriteLock());
399 writeUnlocker.accept(lock, s);
400 }
401
402 lock.asWriteLock().lock();
403 lock.asWriteLock().unlock();
404
405 assertTrue(Thread.interrupted());
406 }
407
408 /**
409 * tryWriteLock on an unlocked lock succeeds
410 */
411 public void testTryWriteLock() {
412 final StampedLock lock = new StampedLock();
413 long s = lock.tryWriteLock();
414 assertTrue(s != 0L);
415 assertTrue(lock.isWriteLocked());
416 assertEquals(0L, lock.tryWriteLock());
417 releaseWriteLock(lock, s);
418 }
419
420 /**
421 * tryWriteLock fails if locked
422 */
423 public void testTryWriteLockWhenLocked() {
424 final StampedLock lock = new StampedLock();
425 long s = lock.writeLock();
426 Thread t = newStartedThread(new CheckedRunnable() {
427 public void realRun() {
428 assertEquals(0L, lock.tryWriteLock());
429 }});
430
431 assertEquals(0L, lock.tryWriteLock());
432 awaitTermination(t);
433 releaseWriteLock(lock, s);
434 }
435
436 /**
437 * tryReadLock fails if write-locked
438 */
439 public void testTryReadLockWhenLocked() {
440 final StampedLock lock = new StampedLock();
441 long s = lock.writeLock();
442 Thread t = newStartedThread(new CheckedRunnable() {
443 public void realRun() {
444 assertEquals(0L, lock.tryReadLock());
445 }});
446
447 assertEquals(0L, lock.tryReadLock());
448 awaitTermination(t);
449 releaseWriteLock(lock, s);
450 }
451
452 /**
453 * Multiple threads can hold a read lock when not write-locked
454 */
455 public void testMultipleReadLocks() {
456 final StampedLock lock = new StampedLock();
457 final long s = lock.readLock();
458 Thread t = newStartedThread(new CheckedRunnable() {
459 public void realRun() throws InterruptedException {
460 long s2 = lock.tryReadLock();
461 assertValid(lock, s2);
462 lock.unlockRead(s2);
463 long s3 = lock.tryReadLock(LONG_DELAY_MS, MILLISECONDS);
464 assertValid(lock, s3);
465 lock.unlockRead(s3);
466 long s4 = lock.readLock();
467 assertValid(lock, s4);
468 lock.unlockRead(s4);
469 lock.asReadLock().lock();
470 lock.asReadLock().unlock();
471 lock.asReadLock().lockInterruptibly();
472 lock.asReadLock().unlock();
473 lock.asReadLock().tryLock(Long.MIN_VALUE, DAYS);
474 lock.asReadLock().unlock();
475 }});
476
477 awaitTermination(t);
478 lock.unlockRead(s);
479 }
480
481 /**
482 * A writelock succeeds only after a reading thread unlocks
483 */
484 public void testWriteAfterReadLock() throws InterruptedException {
485 final CountDownLatch running = new CountDownLatch(1);
486 final StampedLock lock = new StampedLock();
487 long rs = lock.readLock();
488 Thread t = newStartedThread(new CheckedRunnable() {
489 public void realRun() {
490 running.countDown();
491 long s = lock.writeLock();
492 lock.unlockWrite(s);
493 }});
494
495 running.await();
496 waitForThreadToEnterWaitState(t, MEDIUM_DELAY_MS);
497 assertFalse(lock.isWriteLocked());
498 lock.unlockRead(rs);
499 awaitTermination(t);
500 assertFalse(lock.isWriteLocked());
501 }
502
503 /**
504 * A writelock succeeds only after reading threads unlock
505 */
506 public void testWriteAfterMultipleReadLocks() {
507 final StampedLock lock = new StampedLock();
508 long s = lock.readLock();
509 Thread t1 = newStartedThread(new CheckedRunnable() {
510 public void realRun() {
511 long rs = lock.readLock();
512 lock.unlockRead(rs);
513 }});
514
515 awaitTermination(t1);
516
517 Thread t2 = newStartedThread(new CheckedRunnable() {
518 public void realRun() {
519 long ws = lock.writeLock();
520 lock.unlockWrite(ws);
521 }});
522
523 assertTrue(lock.isReadLocked());
524 assertFalse(lock.isWriteLocked());
525 lock.unlockRead(s);
526 awaitTermination(t2);
527 assertFalse(lock.isWriteLocked());
528 }
529
530 /**
531 * Readlocks succeed only after a writing thread unlocks
532 */
533 public void testReadAfterWriteLock() {
534 final StampedLock lock = new StampedLock();
535 final CountDownLatch threadsStarted = new CountDownLatch(2);
536 final long s = lock.writeLock();
537 Thread t1 = newStartedThread(new CheckedRunnable() {
538 public void realRun() {
539 threadsStarted.countDown();
540 long rs = lock.readLock();
541 lock.unlockRead(rs);
542 }});
543 Thread t2 = newStartedThread(new CheckedRunnable() {
544 public void realRun() {
545 threadsStarted.countDown();
546 long rs = lock.readLock();
547 lock.unlockRead(rs);
548 }});
549
550 await(threadsStarted);
551 waitForThreadToEnterWaitState(t1, MEDIUM_DELAY_MS);
552 waitForThreadToEnterWaitState(t2, MEDIUM_DELAY_MS);
553 releaseWriteLock(lock, s);
554 awaitTermination(t1);
555 awaitTermination(t2);
556 }
557
558 /**
559 * tryReadLock succeeds if read locked but not write locked
560 */
561 public void testTryLockWhenReadLocked() {
562 final StampedLock lock = new StampedLock();
563 long s = lock.readLock();
564 Thread t = newStartedThread(new CheckedRunnable() {
565 public void realRun() {
566 long rs = lock.tryReadLock();
567 assertValid(lock, rs);
568 lock.unlockRead(rs);
569 }});
570
571 awaitTermination(t);
572 lock.unlockRead(s);
573 }
574
575 /**
576 * tryWriteLock fails when read locked
577 */
578 public void testTryWriteLockWhenReadLocked() {
579 final StampedLock lock = new StampedLock();
580 long s = lock.readLock();
581 Thread t = newStartedThread(new CheckedRunnable() {
582 public void realRun() {
583 threadAssertEquals(0L, lock.tryWriteLock());
584 }});
585
586 awaitTermination(t);
587 lock.unlockRead(s);
588 }
589
590 /**
591 * timed lock operations time out if lock not available
592 */
593 public void testTimedLock_Timeout() throws Exception {
594 ArrayList<Future<?>> futures = new ArrayList<>();
595
596 // Write locked
597 final StampedLock lock = new StampedLock();
598 long stamp = lock.writeLock();
599 assertEquals(0L, lock.tryReadLock(0L, DAYS));
600 assertEquals(0L, lock.tryReadLock(Long.MIN_VALUE, DAYS));
601 assertFalse(lock.asReadLock().tryLock(0L, DAYS));
602 assertFalse(lock.asReadLock().tryLock(Long.MIN_VALUE, DAYS));
603 assertEquals(0L, lock.tryWriteLock(0L, DAYS));
604 assertEquals(0L, lock.tryWriteLock(Long.MIN_VALUE, DAYS));
605 assertFalse(lock.asWriteLock().tryLock(0L, DAYS));
606 assertFalse(lock.asWriteLock().tryLock(Long.MIN_VALUE, DAYS));
607
608 futures.add(cachedThreadPool.submit(new CheckedRunnable() {
609 public void realRun() throws InterruptedException {
610 long startTime = System.nanoTime();
611 assertEquals(0L, lock.tryWriteLock(timeoutMillis(), MILLISECONDS));
612 assertTrue(millisElapsedSince(startTime) >= timeoutMillis());
613 }}));
614
615 futures.add(cachedThreadPool.submit(new CheckedRunnable() {
616 public void realRun() throws InterruptedException {
617 long startTime = System.nanoTime();
618 assertEquals(0L, lock.tryReadLock(timeoutMillis(), MILLISECONDS));
619 assertTrue(millisElapsedSince(startTime) >= timeoutMillis());
620 }}));
621
622 // Read locked
623 final StampedLock lock2 = new StampedLock();
624 long stamp2 = lock2.readLock();
625 assertEquals(0L, lock2.tryWriteLock(0L, DAYS));
626 assertEquals(0L, lock2.tryWriteLock(Long.MIN_VALUE, DAYS));
627 assertFalse(lock2.asWriteLock().tryLock(0L, DAYS));
628 assertFalse(lock2.asWriteLock().tryLock(Long.MIN_VALUE, DAYS));
629
630 futures.add(cachedThreadPool.submit(new CheckedRunnable() {
631 public void realRun() throws InterruptedException {
632 long startTime = System.nanoTime();
633 assertEquals(0L, lock2.tryWriteLock(timeoutMillis(), MILLISECONDS));
634 assertTrue(millisElapsedSince(startTime) >= timeoutMillis());
635 }}));
636
637 for (Future<?> future : futures)
638 assertNull(future.get());
639
640 releaseWriteLock(lock, stamp);
641 releaseReadLock(lock2, stamp2);
642 }
643
644 /**
645 * writeLockInterruptibly succeeds if unlocked
646 */
647 public void testWriteLockInterruptibly() throws InterruptedException {
648 final StampedLock lock = new StampedLock();
649 long s = lock.writeLockInterruptibly();
650 assertTrue(lock.isWriteLocked());
651 releaseWriteLock(lock, s);
652 }
653
654 /**
655 * readLockInterruptibly succeeds if lock free
656 */
657 public void testReadLockInterruptibly() throws InterruptedException {
658 final StampedLock lock = new StampedLock();
659
660 long s = assertValid(lock, lock.readLockInterruptibly());
661 assertTrue(lock.isReadLocked());
662 lock.unlockRead(s);
663
664 lock.asReadLock().lockInterruptibly();
665 assertTrue(lock.isReadLocked());
666 lock.asReadLock().unlock();
667 }
668
669 /**
670 * A serialized lock deserializes as unlocked
671 */
672 public void testSerialization() {
673 StampedLock lock = new StampedLock();
674 lock.writeLock();
675 StampedLock clone = serialClone(lock);
676 assertTrue(lock.isWriteLocked());
677 assertFalse(clone.isWriteLocked());
678 long s = clone.writeLock();
679 assertTrue(clone.isWriteLocked());
680 clone.unlockWrite(s);
681 assertFalse(clone.isWriteLocked());
682 }
683
684 /**
685 * toString indicates current lock state
686 */
687 public void testToString() {
688 StampedLock lock = new StampedLock();
689 assertTrue(lock.toString().contains("Unlocked"));
690 long s = lock.writeLock();
691 assertTrue(lock.toString().contains("Write-locked"));
692 lock.unlockWrite(s);
693 s = lock.readLock();
694 assertTrue(lock.toString().contains("Read-locks"));
695 }
696
697 /**
698 * tryOptimisticRead succeeds and validates if unlocked, fails if
699 * exclusively locked
700 */
701 public void testValidateOptimistic() throws InterruptedException {
702 StampedLock lock = new StampedLock();
703
704 assertValid(lock, lock.tryOptimisticRead());
705
706 for (Function<StampedLock, Long> writeLocker : writeLockers()) {
707 long s = assertValid(lock, writeLocker.apply(lock));
708 assertEquals(0L, lock.tryOptimisticRead());
709 releaseWriteLock(lock, s);
710 }
711
712 for (Function<StampedLock, Long> readLocker : readLockers()) {
713 long s = assertValid(lock, readLocker.apply(lock));
714 long p = assertValid(lock, lock.tryOptimisticRead());
715 releaseReadLock(lock, s);
716 assertTrue(lock.validate(p));
717 }
718
719 assertValid(lock, lock.tryOptimisticRead());
720 }
721
722 /**
723 * tryOptimisticRead stamp does not validate if a write lock intervenes
724 */
725 public void testValidateOptimisticWriteLocked() {
726 final StampedLock lock = new StampedLock();
727 final long p = assertValid(lock, lock.tryOptimisticRead());
728 final long s = assertValid(lock, lock.writeLock());
729 assertFalse(lock.validate(p));
730 assertEquals(0L, lock.tryOptimisticRead());
731 assertTrue(lock.validate(s));
732 lock.unlockWrite(s);
733 }
734
735 /**
736 * tryOptimisticRead stamp does not validate if a write lock
737 * intervenes in another thread
738 */
739 public void testValidateOptimisticWriteLocked2()
740 throws InterruptedException {
741 final CountDownLatch running = new CountDownLatch(1);
742 final StampedLock lock = new StampedLock();
743 final long p = assertValid(lock, lock.tryOptimisticRead());
744
745 Thread t = newStartedThread(new CheckedInterruptedRunnable() {
746 public void realRun() throws InterruptedException {
747 lock.writeLockInterruptibly();
748 running.countDown();
749 lock.writeLockInterruptibly();
750 }});
751
752 running.await();
753 assertFalse(lock.validate(p));
754 assertEquals(0L, lock.tryOptimisticRead());
755 t.interrupt();
756 awaitTermination(t);
757 }
758
759 /**
760 * tryConvertToOptimisticRead succeeds and validates if successfully locked
761 */
762 public void testTryConvertToOptimisticRead() throws InterruptedException {
763 StampedLock lock = new StampedLock();
764 long s, p, q;
765 assertEquals(0L, lock.tryConvertToOptimisticRead(0L));
766
767 s = assertValid(lock, lock.tryOptimisticRead());
768 assertEquals(s, lock.tryConvertToOptimisticRead(s));
769 assertTrue(lock.validate(s));
770
771 for (Function<StampedLock, Long> writeLocker : writeLockers()) {
772 s = assertValid(lock, writeLocker.apply(lock));
773 p = assertValid(lock, lock.tryConvertToOptimisticRead(s));
774 assertFalse(lock.validate(s));
775 assertTrue(lock.validate(p));
776 assertUnlocked(lock);
777 }
778
779 for (Function<StampedLock, Long> readLocker : readLockers()) {
780 s = assertValid(lock, readLocker.apply(lock));
781 q = assertValid(lock, lock.tryOptimisticRead());
782 assertEquals(q, lock.tryConvertToOptimisticRead(q));
783 assertTrue(lock.validate(q));
784 assertTrue(lock.isReadLocked());
785 p = assertValid(lock, lock.tryConvertToOptimisticRead(s));
786 assertTrue(lock.validate(p));
787 assertTrue(lock.validate(s));
788 assertUnlocked(lock);
789 assertEquals(q, lock.tryConvertToOptimisticRead(q));
790 assertTrue(lock.validate(q));
791 }
792 }
793
794 /**
795 * tryConvertToReadLock succeeds for valid stamps
796 */
797 public void testTryConvertToReadLock() throws InterruptedException {
798 StampedLock lock = new StampedLock();
799 long s, p;
800
801 assertEquals(0L, lock.tryConvertToReadLock(0L));
802
803 s = assertValid(lock, lock.tryOptimisticRead());
804 p = assertValid(lock, lock.tryConvertToReadLock(s));
805 assertTrue(lock.isReadLocked());
806 assertEquals(1, lock.getReadLockCount());
807 assertTrue(lock.validate(s));
808 lock.unlockRead(p);
809
810 s = assertValid(lock, lock.tryOptimisticRead());
811 lock.readLock();
812 p = assertValid(lock, lock.tryConvertToReadLock(s));
813 assertTrue(lock.isReadLocked());
814 assertEquals(2, lock.getReadLockCount());
815 lock.unlockRead(p);
816 lock.unlockRead(p);
817 assertUnlocked(lock);
818
819 for (BiConsumer<StampedLock, Long> readUnlocker : readUnlockers()) {
820 for (Function<StampedLock, Long> writeLocker : writeLockers()) {
821 s = assertValid(lock, writeLocker.apply(lock));
822 p = assertValid(lock, lock.tryConvertToReadLock(s));
823 assertFalse(lock.validate(s));
824 assertTrue(lock.isReadLocked());
825 assertEquals(1, lock.getReadLockCount());
826 readUnlocker.accept(lock, p);
827 }
828
829 for (Function<StampedLock, Long> readLocker : readLockers()) {
830 s = assertValid(lock, readLocker.apply(lock));
831 assertEquals(s, lock.tryConvertToReadLock(s));
832 assertTrue(lock.validate(s));
833 assertTrue(lock.isReadLocked());
834 assertEquals(1, lock.getReadLockCount());
835 readUnlocker.accept(lock, s);
836 }
837 }
838 }
839
840 /**
841 * tryConvertToWriteLock succeeds if lock available; fails if multiply read locked
842 */
843 public void testTryConvertToWriteLock() throws InterruptedException {
844 StampedLock lock = new StampedLock();
845 long s, p;
846
847 assertEquals(0L, lock.tryConvertToWriteLock(0L));
848
849 assertTrue((s = lock.tryOptimisticRead()) != 0L);
850 assertTrue((p = lock.tryConvertToWriteLock(s)) != 0L);
851 assertTrue(lock.isWriteLocked());
852 lock.unlockWrite(p);
853
854 for (BiConsumer<StampedLock, Long> writeUnlocker : writeUnlockers()) {
855 for (Function<StampedLock, Long> writeLocker : writeLockers()) {
856 s = assertValid(lock, writeLocker.apply(lock));
857 assertEquals(s, lock.tryConvertToWriteLock(s));
858 assertTrue(lock.validate(s));
859 assertTrue(lock.isWriteLocked());
860 writeUnlocker.accept(lock, s);
861 }
862
863 for (Function<StampedLock, Long> readLocker : readLockers()) {
864 s = assertValid(lock, readLocker.apply(lock));
865 p = assertValid(lock, lock.tryConvertToWriteLock(s));
866 assertFalse(lock.validate(s));
867 assertTrue(lock.validate(p));
868 assertTrue(lock.isWriteLocked());
869 writeUnlocker.accept(lock, p);
870 }
871 }
872
873 // failure if multiply read locked
874 for (Function<StampedLock, Long> readLocker : readLockers()) {
875 s = assertValid(lock, readLocker.apply(lock));
876 p = assertValid(lock, readLocker.apply(lock));
877 assertEquals(0L, lock.tryConvertToWriteLock(s));
878 assertTrue(lock.validate(s));
879 assertTrue(lock.validate(p));
880 assertEquals(2, lock.getReadLockCount());
881 lock.unlock(p);
882 lock.unlock(s);
883 assertUnlocked(lock);
884 }
885 }
886
887 /**
888 * asWriteLock can be locked and unlocked
889 */
890 public void testAsWriteLock() throws Throwable {
891 StampedLock sl = new StampedLock();
892 Lock lock = sl.asWriteLock();
893 for (Action locker : lockLockers(lock)) {
894 locker.run();
895 assertTrue(sl.isWriteLocked());
896 assertFalse(sl.isReadLocked());
897 assertFalse(lock.tryLock());
898 lock.unlock();
899 assertUnlocked(sl);
900 }
901 }
902
903 /**
904 * asReadLock can be locked and unlocked
905 */
906 public void testAsReadLock() throws Throwable {
907 StampedLock sl = new StampedLock();
908 Lock lock = sl.asReadLock();
909 for (Action locker : lockLockers(lock)) {
910 locker.run();
911 assertTrue(sl.isReadLocked());
912 assertFalse(sl.isWriteLocked());
913 assertEquals(1, sl.getReadLockCount());
914 locker.run();
915 assertTrue(sl.isReadLocked());
916 assertEquals(2, sl.getReadLockCount());
917 lock.unlock();
918 lock.unlock();
919 assertUnlocked(sl);
920 }
921 }
922
923 /**
924 * asReadWriteLock.writeLock can be locked and unlocked
925 */
926 public void testAsReadWriteLockWriteLock() throws Throwable {
927 StampedLock sl = new StampedLock();
928 Lock lock = sl.asReadWriteLock().writeLock();
929 for (Action locker : lockLockers(lock)) {
930 locker.run();
931 assertTrue(sl.isWriteLocked());
932 assertFalse(sl.isReadLocked());
933 assertFalse(lock.tryLock());
934 lock.unlock();
935 assertUnlocked(sl);
936 }
937 }
938
939 /**
940 * asReadWriteLock.readLock can be locked and unlocked
941 */
942 public void testAsReadWriteLockReadLock() throws Throwable {
943 StampedLock sl = new StampedLock();
944 Lock lock = sl.asReadWriteLock().readLock();
945 for (Action locker : lockLockers(lock)) {
946 locker.run();
947 assertTrue(sl.isReadLocked());
948 assertFalse(sl.isWriteLocked());
949 assertEquals(1, sl.getReadLockCount());
950 locker.run();
951 assertTrue(sl.isReadLocked());
952 assertEquals(2, sl.getReadLockCount());
953 lock.unlock();
954 lock.unlock();
955 assertUnlocked(sl);
956 }
957 }
958
959 /**
960 * Lock.newCondition throws UnsupportedOperationException
961 */
962 public void testLockViewsDoNotSupportConditions() {
963 StampedLock sl = new StampedLock();
964 assertThrows(UnsupportedOperationException.class,
965 () -> sl.asWriteLock().newCondition(),
966 () -> sl.asReadLock().newCondition(),
967 () -> sl.asReadWriteLock().writeLock().newCondition(),
968 () -> sl.asReadWriteLock().readLock().newCondition());
969 }
970
971 /**
972 * Passing optimistic read stamps to unlock operations result in
973 * IllegalMonitorStateException
974 */
975 public void testCannotUnlockOptimisticReadStamps() {
976 Runnable[] actions = {
977 () -> {
978 StampedLock sl = new StampedLock();
979 long stamp = assertValid(sl, sl.tryOptimisticRead());
980 sl.unlockRead(stamp);
981 },
982 () -> {
983 StampedLock sl = new StampedLock();
984 long stamp = sl.tryOptimisticRead();
985 sl.unlock(stamp);
986 },
987
988 () -> {
989 StampedLock sl = new StampedLock();
990 long stamp = sl.tryOptimisticRead();
991 sl.writeLock();
992 sl.unlock(stamp);
993 },
994 () -> {
995 StampedLock sl = new StampedLock();
996 sl.readLock();
997 long stamp = assertValid(sl, sl.tryOptimisticRead());
998 sl.unlockRead(stamp);
999 },
1000 () -> {
1001 StampedLock sl = new StampedLock();
1002 sl.readLock();
1003 long stamp = assertValid(sl, sl.tryOptimisticRead());
1004 sl.unlock(stamp);
1005 },
1006
1007 () -> {
1008 StampedLock sl = new StampedLock();
1009 long stamp = sl.tryConvertToOptimisticRead(sl.writeLock());
1010 assertValid(sl, stamp);
1011 sl.writeLock();
1012 sl.unlockWrite(stamp);
1013 },
1014 () -> {
1015 StampedLock sl = new StampedLock();
1016 long stamp = sl.tryConvertToOptimisticRead(sl.writeLock());
1017 sl.writeLock();
1018 sl.unlock(stamp);
1019 },
1020 () -> {
1021 StampedLock sl = new StampedLock();
1022 long stamp = sl.tryConvertToOptimisticRead(sl.writeLock());
1023 sl.readLock();
1024 sl.unlockRead(stamp);
1025 },
1026 () -> {
1027 StampedLock sl = new StampedLock();
1028 long stamp = sl.tryConvertToOptimisticRead(sl.writeLock());
1029 sl.readLock();
1030 sl.unlock(stamp);
1031 },
1032
1033 () -> {
1034 StampedLock sl = new StampedLock();
1035 long stamp = sl.tryConvertToOptimisticRead(sl.readLock());
1036 assertValid(sl, stamp);
1037 sl.writeLock();
1038 sl.unlockWrite(stamp);
1039 },
1040 () -> {
1041 StampedLock sl = new StampedLock();
1042 long stamp = sl.tryConvertToOptimisticRead(sl.readLock());
1043 sl.writeLock();
1044 sl.unlock(stamp);
1045 },
1046 () -> {
1047 StampedLock sl = new StampedLock();
1048 long stamp = sl.tryConvertToOptimisticRead(sl.readLock());
1049 sl.readLock();
1050 sl.unlockRead(stamp);
1051 },
1052 () -> {
1053 StampedLock sl = new StampedLock();
1054 sl.readLock();
1055 long stamp = sl.tryConvertToOptimisticRead(sl.readLock());
1056 assertValid(sl, stamp);
1057 sl.readLock();
1058 sl.unlockRead(stamp);
1059 },
1060 () -> {
1061 StampedLock sl = new StampedLock();
1062 long stamp = sl.tryConvertToOptimisticRead(sl.readLock());
1063 sl.readLock();
1064 sl.unlock(stamp);
1065 },
1066 () -> {
1067 StampedLock sl = new StampedLock();
1068 sl.readLock();
1069 long stamp = sl.tryConvertToOptimisticRead(sl.readLock());
1070 sl.readLock();
1071 sl.unlock(stamp);
1072 },
1073 };
1074
1075 assertThrows(IllegalMonitorStateException.class, actions);
1076 }
1077
1078 static long writeLockInterruptiblyUninterrupted(StampedLock sl) {
1079 try { return sl.writeLockInterruptibly(); }
1080 catch (InterruptedException ex) { throw new AssertionError(ex); }
1081 }
1082
1083 static long tryWriteLockUninterrupted(StampedLock sl, long time, TimeUnit unit) {
1084 try { return sl.tryWriteLock(time, unit); }
1085 catch (InterruptedException ex) { throw new AssertionError(ex); }
1086 }
1087
1088 static long readLockInterruptiblyUninterrupted(StampedLock sl) {
1089 try { return sl.readLockInterruptibly(); }
1090 catch (InterruptedException ex) { throw new AssertionError(ex); }
1091 }
1092
1093 static long tryReadLockUninterrupted(StampedLock sl, long time, TimeUnit unit) {
1094 try { return sl.tryReadLock(time, unit); }
1095 catch (InterruptedException ex) { throw new AssertionError(ex); }
1096 }
1097
1098 /**
1099 * Invalid stamps result in IllegalMonitorStateException
1100 */
1101 public void testInvalidStampsThrowIllegalMonitorStateException() {
1102 final StampedLock sl = new StampedLock();
1103
1104 assertThrows(IllegalMonitorStateException.class,
1105 () -> sl.unlockWrite(0L),
1106 () -> sl.unlockRead(0L),
1107 () -> sl.unlock(0L));
1108
1109 final long optimisticStamp = sl.tryOptimisticRead();
1110 final long readStamp = sl.readLock();
1111 sl.unlockRead(readStamp);
1112 final long writeStamp = sl.writeLock();
1113 sl.unlockWrite(writeStamp);
1114 assertTrue(optimisticStamp != 0L && readStamp != 0L && writeStamp != 0L);
1115 final long[] noLongerValidStamps = { optimisticStamp, readStamp, writeStamp };
1116 final Runnable assertNoLongerValidStampsThrow = () -> {
1117 for (long noLongerValidStamp : noLongerValidStamps)
1118 assertThrows(IllegalMonitorStateException.class,
1119 () -> sl.unlockWrite(noLongerValidStamp),
1120 () -> sl.unlockRead(noLongerValidStamp),
1121 () -> sl.unlock(noLongerValidStamp));
1122 };
1123 assertNoLongerValidStampsThrow.run();
1124
1125 for (Function<StampedLock, Long> readLocker : readLockers())
1126 for (BiConsumer<StampedLock, Long> readUnlocker : readUnlockers()) {
1127 final long stamp = readLocker.apply(sl);
1128 assertValid(sl, stamp);
1129 assertNoLongerValidStampsThrow.run();
1130 assertThrows(IllegalMonitorStateException.class,
1131 () -> sl.unlockWrite(stamp),
1132 () -> sl.unlockRead(sl.tryOptimisticRead()),
1133 () -> sl.unlockRead(0L));
1134 readUnlocker.accept(sl, stamp);
1135 assertUnlocked(sl);
1136 assertNoLongerValidStampsThrow.run();
1137 }
1138
1139 for (Function<StampedLock, Long> writeLocker : writeLockers())
1140 for (BiConsumer<StampedLock, Long> writeUnlocker : writeUnlockers()) {
1141 final long stamp = writeLocker.apply(sl);
1142 assertValid(sl, stamp);
1143 assertNoLongerValidStampsThrow.run();
1144 assertThrows(IllegalMonitorStateException.class,
1145 () -> sl.unlockRead(stamp),
1146 () -> sl.unlockWrite(0L));
1147 writeUnlocker.accept(sl, stamp);
1148 assertUnlocked(sl);
1149 assertNoLongerValidStampsThrow.run();
1150 }
1151 }
1152
1153 /**
1154 * Read locks can be very deeply nested
1155 */
1156 public void testDeeplyNestedReadLocks() {
1157 final StampedLock lock = new StampedLock();
1158 final int depth = 300;
1159 final long[] stamps = new long[depth];
1160 final List<Function<StampedLock, Long>> readLockers = readLockers();
1161 final List<BiConsumer<StampedLock, Long>> readUnlockers = readUnlockers();
1162 for (int i = 0; i < depth; i++) {
1163 Function<StampedLock, Long> readLocker
1164 = readLockers.get(i % readLockers.size());
1165 long stamp = readLocker.apply(lock);
1166 assertEquals(i + 1, lock.getReadLockCount());
1167 assertTrue(lock.isReadLocked());
1168 stamps[i] = stamp;
1169 }
1170 for (int i = 0; i < depth; i++) {
1171 BiConsumer<StampedLock, Long> readUnlocker
1172 = readUnlockers.get(i % readUnlockers.size());
1173 assertEquals(depth - i, lock.getReadLockCount());
1174 assertTrue(lock.isReadLocked());
1175 readUnlocker.accept(lock, stamps[depth - 1 - i]);
1176 }
1177 assertUnlocked(lock);
1178 }
1179 }