1 /* 2 * Written by Doug Lea with assistance from members of JCP JSR-166 3 * Expert Group and released to the public domain, as explained at 4 * http://creativecommons.org/publicdomain/zero/1.0/ 5 * Other contributors include Andrew Wright, Jeffrey Hayes, 6 * Pat Fisher, Mike Judd. 7 */ 8 9 package jsr166; 10 11 import static java.util.concurrent.TimeUnit.MILLISECONDS; 12 13 import java.util.Collection; 14 import java.util.concurrent.CountDownLatch; 15 import java.util.concurrent.Semaphore; 16 17 import junit.framework.AssertionFailedError; 18 import junit.framework.Test; 19 import junit.framework.TestSuite; 20 21 public class SemaphoreTest extends JSR166TestCase { 22 // android-note: Removed because the CTS runner does a bad job of 23 // retrying tests that have suite() declarations. 24 // 25 // public static void main(String[] args) { 26 // main(suite(), args); 27 // } 28 // public static Test suite() { 29 // return new TestSuite(SemaphoreTest.class); 30 // } 31 32 /** 33 * Subclass to expose protected methods 34 */ 35 static class PublicSemaphore extends Semaphore { PublicSemaphore(int permits)36 PublicSemaphore(int permits) { super(permits); } PublicSemaphore(int permits, boolean fair)37 PublicSemaphore(int permits, boolean fair) { super(permits, fair); } getQueuedThreads()38 public Collection<Thread> getQueuedThreads() { 39 return super.getQueuedThreads(); 40 } hasQueuedThread(Thread t)41 public boolean hasQueuedThread(Thread t) { 42 return super.getQueuedThreads().contains(t); 43 } reducePermits(int reduction)44 public void reducePermits(int reduction) { 45 super.reducePermits(reduction); 46 } 47 } 48 49 /** 50 * A runnable calling acquire 51 */ 52 class InterruptibleLockRunnable extends CheckedRunnable { 53 final Semaphore lock; InterruptibleLockRunnable(Semaphore s)54 InterruptibleLockRunnable(Semaphore s) { lock = s; } realRun()55 public void realRun() { 56 try { 57 lock.acquire(); 58 } 59 catch (InterruptedException ignored) {} 60 } 61 } 62 63 /** 64 * A runnable calling acquire that expects to be interrupted 65 */ 66 class InterruptedLockRunnable extends CheckedInterruptedRunnable { 67 final Semaphore lock; InterruptedLockRunnable(Semaphore s)68 InterruptedLockRunnable(Semaphore s) { lock = s; } realRun()69 public void realRun() throws InterruptedException { 70 lock.acquire(); 71 } 72 } 73 74 /** 75 * Spin-waits until s.hasQueuedThread(t) becomes true. 76 */ waitForQueuedThread(PublicSemaphore s, Thread t)77 void waitForQueuedThread(PublicSemaphore s, Thread t) { 78 long startTime = System.nanoTime(); 79 while (!s.hasQueuedThread(t)) { 80 if (millisElapsedSince(startTime) > LONG_DELAY_MS) 81 throw new AssertionFailedError("timed out"); 82 Thread.yield(); 83 } 84 assertTrue(s.hasQueuedThreads()); 85 assertTrue(t.isAlive()); 86 } 87 88 /** 89 * Spin-waits until s.hasQueuedThreads() becomes true. 90 */ waitForQueuedThreads(Semaphore s)91 void waitForQueuedThreads(Semaphore s) { 92 long startTime = System.nanoTime(); 93 while (!s.hasQueuedThreads()) { 94 if (millisElapsedSince(startTime) > LONG_DELAY_MS) 95 throw new AssertionFailedError("timed out"); 96 Thread.yield(); 97 } 98 } 99 100 enum AcquireMethod { acquire()101 acquire() { 102 void acquire(Semaphore s) throws InterruptedException { 103 s.acquire(); 104 } 105 }, acquireN()106 acquireN() { 107 void acquire(Semaphore s, int permits) throws InterruptedException { 108 s.acquire(permits); 109 } 110 }, acquireUninterruptibly()111 acquireUninterruptibly() { 112 void acquire(Semaphore s) { 113 s.acquireUninterruptibly(); 114 } 115 }, acquireUninterruptiblyN()116 acquireUninterruptiblyN() { 117 void acquire(Semaphore s, int permits) { 118 s.acquireUninterruptibly(permits); 119 } 120 }, tryAcquire()121 tryAcquire() { 122 void acquire(Semaphore s) { 123 assertTrue(s.tryAcquire()); 124 } 125 }, tryAcquireN()126 tryAcquireN() { 127 void acquire(Semaphore s, int permits) { 128 assertTrue(s.tryAcquire(permits)); 129 } 130 }, tryAcquireTimed()131 tryAcquireTimed() { 132 void acquire(Semaphore s) throws InterruptedException { 133 assertTrue(s.tryAcquire(2 * LONG_DELAY_MS, MILLISECONDS)); 134 } 135 }, 136 tryAcquireTimedN { acquire(Semaphore s, int permits)137 void acquire(Semaphore s, int permits) throws InterruptedException { 138 assertTrue(s.tryAcquire(permits, 2 * LONG_DELAY_MS, MILLISECONDS)); 139 } 140 }; 141 142 // Intentionally meta-circular 143 144 /** Acquires 1 permit. */ acquire(Semaphore s)145 void acquire(Semaphore s) throws InterruptedException { 146 acquire(s, 1); 147 } 148 /** Acquires the given number of permits. */ acquire(Semaphore s, int permits)149 void acquire(Semaphore s, int permits) throws InterruptedException { 150 for (int i = 0; i < permits; i++) 151 acquire(s); 152 } 153 } 154 155 /** 156 * Zero, negative, and positive initial values are allowed in constructor 157 */ testConstructor()158 public void testConstructor() { testConstructor(false); } testConstructor_fair()159 public void testConstructor_fair() { testConstructor(true); } testConstructor(boolean fair)160 public void testConstructor(boolean fair) { 161 for (int permits : new int[] { -42, -1, 0, 1, 42 }) { 162 Semaphore s = new Semaphore(permits, fair); 163 assertEquals(permits, s.availablePermits()); 164 assertEquals(fair, s.isFair()); 165 } 166 } 167 168 /** 169 * Constructor without fairness argument behaves as nonfair 170 */ testConstructorDefaultsToNonFair()171 public void testConstructorDefaultsToNonFair() { 172 for (int permits : new int[] { -42, -1, 0, 1, 42 }) { 173 Semaphore s = new Semaphore(permits); 174 assertEquals(permits, s.availablePermits()); 175 assertFalse(s.isFair()); 176 } 177 } 178 179 /** 180 * tryAcquire succeeds when sufficient permits, else fails 181 */ testTryAcquireInSameThread()182 public void testTryAcquireInSameThread() { testTryAcquireInSameThread(false); } testTryAcquireInSameThread_fair()183 public void testTryAcquireInSameThread_fair() { testTryAcquireInSameThread(true); } testTryAcquireInSameThread(boolean fair)184 public void testTryAcquireInSameThread(boolean fair) { 185 Semaphore s = new Semaphore(2, fair); 186 assertEquals(2, s.availablePermits()); 187 assertTrue(s.tryAcquire()); 188 assertTrue(s.tryAcquire()); 189 assertEquals(0, s.availablePermits()); 190 assertFalse(s.tryAcquire()); 191 assertFalse(s.tryAcquire()); 192 assertEquals(0, s.availablePermits()); 193 } 194 195 /** 196 * timed tryAcquire times out 197 */ testTryAcquire_timeout()198 public void testTryAcquire_timeout() { testTryAcquire_timeout(false); } testTryAcquire_timeout_fair()199 public void testTryAcquire_timeout_fair() { testTryAcquire_timeout(true); } testTryAcquire_timeout(boolean fair)200 public void testTryAcquire_timeout(boolean fair) { 201 Semaphore s = new Semaphore(0, fair); 202 long startTime = System.nanoTime(); 203 try { assertFalse(s.tryAcquire(timeoutMillis(), MILLISECONDS)); } 204 catch (InterruptedException e) { threadUnexpectedException(e); } 205 assertTrue(millisElapsedSince(startTime) >= timeoutMillis()); 206 } 207 208 /** 209 * timed tryAcquire(N) times out 210 */ testTryAcquireN_timeout()211 public void testTryAcquireN_timeout() { testTryAcquireN_timeout(false); } testTryAcquireN_timeout_fair()212 public void testTryAcquireN_timeout_fair() { testTryAcquireN_timeout(true); } testTryAcquireN_timeout(boolean fair)213 public void testTryAcquireN_timeout(boolean fair) { 214 Semaphore s = new Semaphore(2, fair); 215 long startTime = System.nanoTime(); 216 try { assertFalse(s.tryAcquire(3, timeoutMillis(), MILLISECONDS)); } 217 catch (InterruptedException e) { threadUnexpectedException(e); } 218 assertTrue(millisElapsedSince(startTime) >= timeoutMillis()); 219 } 220 221 /** 222 * acquire(), acquire(N), timed tryAcquired, timed tryAcquire(N) 223 * are interruptible 224 */ testInterruptible_acquire()225 public void testInterruptible_acquire() { testInterruptible(false, AcquireMethod.acquire); } testInterruptible_acquire_fair()226 public void testInterruptible_acquire_fair() { testInterruptible(true, AcquireMethod.acquire); } testInterruptible_acquireN()227 public void testInterruptible_acquireN() { testInterruptible(false, AcquireMethod.acquireN); } testInterruptible_acquireN_fair()228 public void testInterruptible_acquireN_fair() { testInterruptible(true, AcquireMethod.acquireN); } testInterruptible_tryAcquireTimed()229 public void testInterruptible_tryAcquireTimed() { testInterruptible(false, AcquireMethod.tryAcquireTimed); } testInterruptible_tryAcquireTimed_fair()230 public void testInterruptible_tryAcquireTimed_fair() { testInterruptible(true, AcquireMethod.tryAcquireTimed); } testInterruptible_tryAcquireTimedN()231 public void testInterruptible_tryAcquireTimedN() { testInterruptible(false, AcquireMethod.tryAcquireTimedN); } testInterruptible_tryAcquireTimedN_fair()232 public void testInterruptible_tryAcquireTimedN_fair() { testInterruptible(true, AcquireMethod.tryAcquireTimedN); } testInterruptible(boolean fair, final AcquireMethod acquirer)233 public void testInterruptible(boolean fair, final AcquireMethod acquirer) { 234 final PublicSemaphore s = new PublicSemaphore(0, fair); 235 final Semaphore pleaseInterrupt = new Semaphore(0, fair); 236 Thread t = newStartedThread(new CheckedRunnable() { 237 public void realRun() { 238 // Interrupt before acquire 239 Thread.currentThread().interrupt(); 240 try { 241 acquirer.acquire(s); 242 shouldThrow(); 243 } catch (InterruptedException success) {} 244 245 // Interrupt during acquire 246 try { 247 acquirer.acquire(s); 248 shouldThrow(); 249 } catch (InterruptedException success) {} 250 251 // Interrupt before acquire(N) 252 Thread.currentThread().interrupt(); 253 try { 254 acquirer.acquire(s, 3); 255 shouldThrow(); 256 } catch (InterruptedException success) {} 257 258 pleaseInterrupt.release(); 259 260 // Interrupt during acquire(N) 261 try { 262 acquirer.acquire(s, 3); 263 shouldThrow(); 264 } catch (InterruptedException success) {} 265 }}); 266 267 waitForQueuedThread(s, t); 268 t.interrupt(); 269 await(pleaseInterrupt); 270 waitForQueuedThread(s, t); 271 t.interrupt(); 272 awaitTermination(t); 273 } 274 275 /** 276 * acquireUninterruptibly(), acquireUninterruptibly(N) are 277 * uninterruptible 278 */ testUninterruptible_acquireUninterruptibly()279 public void testUninterruptible_acquireUninterruptibly() { testUninterruptible(false, AcquireMethod.acquireUninterruptibly); } testUninterruptible_acquireUninterruptibly_fair()280 public void testUninterruptible_acquireUninterruptibly_fair() { testUninterruptible(true, AcquireMethod.acquireUninterruptibly); } testUninterruptible_acquireUninterruptiblyN()281 public void testUninterruptible_acquireUninterruptiblyN() { testUninterruptible(false, AcquireMethod.acquireUninterruptiblyN); } testUninterruptible_acquireUninterruptiblyN_fair()282 public void testUninterruptible_acquireUninterruptiblyN_fair() { testUninterruptible(true, AcquireMethod.acquireUninterruptiblyN); } testUninterruptible(boolean fair, final AcquireMethod acquirer)283 public void testUninterruptible(boolean fair, final AcquireMethod acquirer) { 284 final PublicSemaphore s = new PublicSemaphore(0, fair); 285 final Semaphore pleaseInterrupt = new Semaphore(-1, fair); 286 287 Thread t1 = newStartedThread(new CheckedRunnable() { 288 public void realRun() throws InterruptedException { 289 // Interrupt before acquire 290 pleaseInterrupt.release(); 291 Thread.currentThread().interrupt(); 292 acquirer.acquire(s); 293 assertTrue(Thread.interrupted()); 294 }}); 295 296 Thread t2 = newStartedThread(new CheckedRunnable() { 297 public void realRun() throws InterruptedException { 298 // Interrupt during acquire 299 pleaseInterrupt.release(); 300 acquirer.acquire(s); 301 assertTrue(Thread.interrupted()); 302 }}); 303 304 await(pleaseInterrupt); 305 waitForQueuedThread(s, t1); 306 waitForQueuedThread(s, t2); 307 t2.interrupt(); 308 309 assertThreadStaysAlive(t1); 310 assertTrue(t2.isAlive()); 311 312 s.release(2); 313 314 awaitTermination(t1); 315 awaitTermination(t2); 316 } 317 318 /** 319 * hasQueuedThreads reports whether there are waiting threads 320 */ testHasQueuedThreads()321 public void testHasQueuedThreads() { testHasQueuedThreads(false); } testHasQueuedThreads_fair()322 public void testHasQueuedThreads_fair() { testHasQueuedThreads(true); } testHasQueuedThreads(boolean fair)323 public void testHasQueuedThreads(boolean fair) { 324 final PublicSemaphore lock = new PublicSemaphore(1, fair); 325 assertFalse(lock.hasQueuedThreads()); 326 lock.acquireUninterruptibly(); 327 Thread t1 = newStartedThread(new InterruptedLockRunnable(lock)); 328 waitForQueuedThread(lock, t1); 329 assertTrue(lock.hasQueuedThreads()); 330 Thread t2 = newStartedThread(new InterruptibleLockRunnable(lock)); 331 waitForQueuedThread(lock, t2); 332 assertTrue(lock.hasQueuedThreads()); 333 t1.interrupt(); 334 awaitTermination(t1); 335 assertTrue(lock.hasQueuedThreads()); 336 lock.release(); 337 awaitTermination(t2); 338 assertFalse(lock.hasQueuedThreads()); 339 } 340 341 /** 342 * getQueueLength reports number of waiting threads 343 */ testGetQueueLength()344 public void testGetQueueLength() { testGetQueueLength(false); } testGetQueueLength_fair()345 public void testGetQueueLength_fair() { testGetQueueLength(true); } testGetQueueLength(boolean fair)346 public void testGetQueueLength(boolean fair) { 347 final PublicSemaphore lock = new PublicSemaphore(1, fair); 348 assertEquals(0, lock.getQueueLength()); 349 lock.acquireUninterruptibly(); 350 Thread t1 = newStartedThread(new InterruptedLockRunnable(lock)); 351 waitForQueuedThread(lock, t1); 352 assertEquals(1, lock.getQueueLength()); 353 Thread t2 = newStartedThread(new InterruptibleLockRunnable(lock)); 354 waitForQueuedThread(lock, t2); 355 assertEquals(2, lock.getQueueLength()); 356 t1.interrupt(); 357 awaitTermination(t1); 358 assertEquals(1, lock.getQueueLength()); 359 lock.release(); 360 awaitTermination(t2); 361 assertEquals(0, lock.getQueueLength()); 362 } 363 364 /** 365 * getQueuedThreads includes waiting threads 366 */ testGetQueuedThreads()367 public void testGetQueuedThreads() { testGetQueuedThreads(false); } testGetQueuedThreads_fair()368 public void testGetQueuedThreads_fair() { testGetQueuedThreads(true); } testGetQueuedThreads(boolean fair)369 public void testGetQueuedThreads(boolean fair) { 370 final PublicSemaphore lock = new PublicSemaphore(1, fair); 371 assertTrue(lock.getQueuedThreads().isEmpty()); 372 lock.acquireUninterruptibly(); 373 assertTrue(lock.getQueuedThreads().isEmpty()); 374 Thread t1 = newStartedThread(new InterruptedLockRunnable(lock)); 375 waitForQueuedThread(lock, t1); 376 assertTrue(lock.getQueuedThreads().contains(t1)); 377 Thread t2 = newStartedThread(new InterruptibleLockRunnable(lock)); 378 waitForQueuedThread(lock, t2); 379 assertTrue(lock.getQueuedThreads().contains(t1)); 380 assertTrue(lock.getQueuedThreads().contains(t2)); 381 t1.interrupt(); 382 awaitTermination(t1); 383 assertFalse(lock.getQueuedThreads().contains(t1)); 384 assertTrue(lock.getQueuedThreads().contains(t2)); 385 lock.release(); 386 awaitTermination(t2); 387 assertTrue(lock.getQueuedThreads().isEmpty()); 388 } 389 390 /** 391 * drainPermits reports and removes given number of permits 392 */ testDrainPermits()393 public void testDrainPermits() { testDrainPermits(false); } testDrainPermits_fair()394 public void testDrainPermits_fair() { testDrainPermits(true); } testDrainPermits(boolean fair)395 public void testDrainPermits(boolean fair) { 396 Semaphore s = new Semaphore(0, fair); 397 assertEquals(0, s.availablePermits()); 398 assertEquals(0, s.drainPermits()); 399 s.release(10); 400 assertEquals(10, s.availablePermits()); 401 assertEquals(10, s.drainPermits()); 402 assertEquals(0, s.availablePermits()); 403 assertEquals(0, s.drainPermits()); 404 } 405 406 /** 407 * release(-N) throws IllegalArgumentException 408 */ testReleaseIAE()409 public void testReleaseIAE() { testReleaseIAE(false); } testReleaseIAE_fair()410 public void testReleaseIAE_fair() { testReleaseIAE(true); } testReleaseIAE(boolean fair)411 public void testReleaseIAE(boolean fair) { 412 Semaphore s = new Semaphore(10, fair); 413 try { 414 s.release(-1); 415 shouldThrow(); 416 } catch (IllegalArgumentException success) {} 417 } 418 419 /** 420 * reducePermits(-N) throws IllegalArgumentException 421 */ testReducePermitsIAE()422 public void testReducePermitsIAE() { testReducePermitsIAE(false); } testReducePermitsIAE_fair()423 public void testReducePermitsIAE_fair() { testReducePermitsIAE(true); } testReducePermitsIAE(boolean fair)424 public void testReducePermitsIAE(boolean fair) { 425 PublicSemaphore s = new PublicSemaphore(10, fair); 426 try { 427 s.reducePermits(-1); 428 shouldThrow(); 429 } catch (IllegalArgumentException success) {} 430 } 431 432 /** 433 * reducePermits reduces number of permits 434 */ testReducePermits()435 public void testReducePermits() { testReducePermits(false); } testReducePermits_fair()436 public void testReducePermits_fair() { testReducePermits(true); } testReducePermits(boolean fair)437 public void testReducePermits(boolean fair) { 438 PublicSemaphore s = new PublicSemaphore(10, fair); 439 assertEquals(10, s.availablePermits()); 440 s.reducePermits(0); 441 assertEquals(10, s.availablePermits()); 442 s.reducePermits(1); 443 assertEquals(9, s.availablePermits()); 444 s.reducePermits(10); 445 assertEquals(-1, s.availablePermits()); 446 s.reducePermits(10); 447 assertEquals(-11, s.availablePermits()); 448 s.reducePermits(0); 449 assertEquals(-11, s.availablePermits()); 450 } 451 452 /** 453 * a reserialized semaphore has same number of permits and 454 * fairness, but no queued threads 455 */ testSerialization()456 public void testSerialization() { testSerialization(false); } testSerialization_fair()457 public void testSerialization_fair() { testSerialization(true); } testSerialization(boolean fair)458 public void testSerialization(boolean fair) { 459 try { 460 Semaphore s = new Semaphore(3, fair); 461 s.acquire(); 462 s.acquire(); 463 s.release(); 464 465 Semaphore clone = serialClone(s); 466 assertEquals(fair, s.isFair()); 467 assertEquals(fair, clone.isFair()); 468 assertEquals(2, s.availablePermits()); 469 assertEquals(2, clone.availablePermits()); 470 clone.acquire(); 471 clone.acquire(); 472 clone.release(); 473 assertEquals(2, s.availablePermits()); 474 assertEquals(1, clone.availablePermits()); 475 assertFalse(s.hasQueuedThreads()); 476 assertFalse(clone.hasQueuedThreads()); 477 } catch (InterruptedException e) { threadUnexpectedException(e); } 478 479 { 480 PublicSemaphore s = new PublicSemaphore(0, fair); 481 Thread t = newStartedThread(new InterruptibleLockRunnable(s)); 482 // waitForQueuedThreads(s); // suffers from "flicker", so ... 483 waitForQueuedThread(s, t); // ... we use this instead 484 PublicSemaphore clone = serialClone(s); 485 assertEquals(fair, s.isFair()); 486 assertEquals(fair, clone.isFair()); 487 assertEquals(0, s.availablePermits()); 488 assertEquals(0, clone.availablePermits()); 489 assertTrue(s.hasQueuedThreads()); 490 assertFalse(clone.hasQueuedThreads()); 491 s.release(); 492 awaitTermination(t); 493 assertFalse(s.hasQueuedThreads()); 494 assertFalse(clone.hasQueuedThreads()); 495 } 496 } 497 498 /** 499 * tryAcquire(n) succeeds when sufficient permits, else fails 500 */ testTryAcquireNInSameThread()501 public void testTryAcquireNInSameThread() { testTryAcquireNInSameThread(false); } testTryAcquireNInSameThread_fair()502 public void testTryAcquireNInSameThread_fair() { testTryAcquireNInSameThread(true); } testTryAcquireNInSameThread(boolean fair)503 public void testTryAcquireNInSameThread(boolean fair) { 504 Semaphore s = new Semaphore(2, fair); 505 assertEquals(2, s.availablePermits()); 506 assertFalse(s.tryAcquire(3)); 507 assertEquals(2, s.availablePermits()); 508 assertTrue(s.tryAcquire(2)); 509 assertEquals(0, s.availablePermits()); 510 assertFalse(s.tryAcquire(1)); 511 assertFalse(s.tryAcquire(2)); 512 assertEquals(0, s.availablePermits()); 513 } 514 515 /** 516 * acquire succeeds if permits available 517 */ testReleaseAcquireSameThread_acquire()518 public void testReleaseAcquireSameThread_acquire() { testReleaseAcquireSameThread(false, AcquireMethod.acquire); } testReleaseAcquireSameThread_acquire_fair()519 public void testReleaseAcquireSameThread_acquire_fair() { testReleaseAcquireSameThread(true, AcquireMethod.acquire); } testReleaseAcquireSameThread_acquireN()520 public void testReleaseAcquireSameThread_acquireN() { testReleaseAcquireSameThread(false, AcquireMethod.acquireN); } testReleaseAcquireSameThread_acquireN_fair()521 public void testReleaseAcquireSameThread_acquireN_fair() { testReleaseAcquireSameThread(true, AcquireMethod.acquireN); } testReleaseAcquireSameThread_acquireUninterruptibly()522 public void testReleaseAcquireSameThread_acquireUninterruptibly() { testReleaseAcquireSameThread(false, AcquireMethod.acquireUninterruptibly); } testReleaseAcquireSameThread_acquireUninterruptibly_fair()523 public void testReleaseAcquireSameThread_acquireUninterruptibly_fair() { testReleaseAcquireSameThread(true, AcquireMethod.acquireUninterruptibly); } testReleaseAcquireSameThread_acquireUninterruptiblyN()524 public void testReleaseAcquireSameThread_acquireUninterruptiblyN() { testReleaseAcquireSameThread(false, AcquireMethod.acquireUninterruptibly); } testReleaseAcquireSameThread_acquireUninterruptiblyN_fair()525 public void testReleaseAcquireSameThread_acquireUninterruptiblyN_fair() { testReleaseAcquireSameThread(true, AcquireMethod.acquireUninterruptibly); } testReleaseAcquireSameThread_tryAcquire()526 public void testReleaseAcquireSameThread_tryAcquire() { testReleaseAcquireSameThread(false, AcquireMethod.tryAcquire); } testReleaseAcquireSameThread_tryAcquire_fair()527 public void testReleaseAcquireSameThread_tryAcquire_fair() { testReleaseAcquireSameThread(true, AcquireMethod.tryAcquire); } testReleaseAcquireSameThread_tryAcquireN()528 public void testReleaseAcquireSameThread_tryAcquireN() { testReleaseAcquireSameThread(false, AcquireMethod.tryAcquireN); } testReleaseAcquireSameThread_tryAcquireN_fair()529 public void testReleaseAcquireSameThread_tryAcquireN_fair() { testReleaseAcquireSameThread(true, AcquireMethod.tryAcquireN); } testReleaseAcquireSameThread_tryAcquireTimed()530 public void testReleaseAcquireSameThread_tryAcquireTimed() { testReleaseAcquireSameThread(false, AcquireMethod.tryAcquireTimed); } testReleaseAcquireSameThread_tryAcquireTimed_fair()531 public void testReleaseAcquireSameThread_tryAcquireTimed_fair() { testReleaseAcquireSameThread(true, AcquireMethod.tryAcquireTimed); } testReleaseAcquireSameThread_tryAcquireTimedN()532 public void testReleaseAcquireSameThread_tryAcquireTimedN() { testReleaseAcquireSameThread(false, AcquireMethod.tryAcquireTimedN); } testReleaseAcquireSameThread_tryAcquireTimedN_fair()533 public void testReleaseAcquireSameThread_tryAcquireTimedN_fair() { testReleaseAcquireSameThread(true, AcquireMethod.tryAcquireTimedN); } testReleaseAcquireSameThread(boolean fair, final AcquireMethod acquirer)534 public void testReleaseAcquireSameThread(boolean fair, 535 final AcquireMethod acquirer) { 536 Semaphore s = new Semaphore(1, fair); 537 for (int i = 1; i < 6; i++) { 538 s.release(i); 539 assertEquals(1 + i, s.availablePermits()); 540 try { 541 acquirer.acquire(s, i); 542 } catch (InterruptedException e) { threadUnexpectedException(e); } 543 assertEquals(1, s.availablePermits()); 544 } 545 } 546 547 /** 548 * release in one thread enables acquire in another thread 549 */ testReleaseAcquireDifferentThreads_acquire()550 public void testReleaseAcquireDifferentThreads_acquire() { testReleaseAcquireDifferentThreads(false, AcquireMethod.acquire); } testReleaseAcquireDifferentThreads_acquire_fair()551 public void testReleaseAcquireDifferentThreads_acquire_fair() { testReleaseAcquireDifferentThreads(true, AcquireMethod.acquire); } testReleaseAcquireDifferentThreads_acquireN()552 public void testReleaseAcquireDifferentThreads_acquireN() { testReleaseAcquireDifferentThreads(false, AcquireMethod.acquireN); } testReleaseAcquireDifferentThreads_acquireN_fair()553 public void testReleaseAcquireDifferentThreads_acquireN_fair() { testReleaseAcquireDifferentThreads(true, AcquireMethod.acquireN); } testReleaseAcquireDifferentThreads_acquireUninterruptibly()554 public void testReleaseAcquireDifferentThreads_acquireUninterruptibly() { testReleaseAcquireDifferentThreads(false, AcquireMethod.acquireUninterruptibly); } testReleaseAcquireDifferentThreads_acquireUninterruptibly_fair()555 public void testReleaseAcquireDifferentThreads_acquireUninterruptibly_fair() { testReleaseAcquireDifferentThreads(true, AcquireMethod.acquireUninterruptibly); } testReleaseAcquireDifferentThreads_acquireUninterruptiblyN()556 public void testReleaseAcquireDifferentThreads_acquireUninterruptiblyN() { testReleaseAcquireDifferentThreads(false, AcquireMethod.acquireUninterruptibly); } testReleaseAcquireDifferentThreads_acquireUninterruptiblyN_fair()557 public void testReleaseAcquireDifferentThreads_acquireUninterruptiblyN_fair() { testReleaseAcquireDifferentThreads(true, AcquireMethod.acquireUninterruptibly); } testReleaseAcquireDifferentThreads_tryAcquireTimed()558 public void testReleaseAcquireDifferentThreads_tryAcquireTimed() { testReleaseAcquireDifferentThreads(false, AcquireMethod.tryAcquireTimed); } testReleaseAcquireDifferentThreads_tryAcquireTimed_fair()559 public void testReleaseAcquireDifferentThreads_tryAcquireTimed_fair() { testReleaseAcquireDifferentThreads(true, AcquireMethod.tryAcquireTimed); } testReleaseAcquireDifferentThreads_tryAcquireTimedN()560 public void testReleaseAcquireDifferentThreads_tryAcquireTimedN() { testReleaseAcquireDifferentThreads(false, AcquireMethod.tryAcquireTimedN); } testReleaseAcquireDifferentThreads_tryAcquireTimedN_fair()561 public void testReleaseAcquireDifferentThreads_tryAcquireTimedN_fair() { testReleaseAcquireDifferentThreads(true, AcquireMethod.tryAcquireTimedN); } testReleaseAcquireDifferentThreads(boolean fair, final AcquireMethod acquirer)562 public void testReleaseAcquireDifferentThreads(boolean fair, 563 final AcquireMethod acquirer) { 564 final Semaphore s = new Semaphore(0, fair); 565 final int rounds = 4; 566 long startTime = System.nanoTime(); 567 Thread t = newStartedThread(new CheckedRunnable() { 568 public void realRun() throws InterruptedException { 569 for (int i = 0; i < rounds; i++) { 570 assertFalse(s.hasQueuedThreads()); 571 if (i % 2 == 0) 572 acquirer.acquire(s); 573 else 574 acquirer.acquire(s, 3); 575 }}}); 576 577 for (int i = 0; i < rounds; i++) { 578 while (! (s.availablePermits() == 0 && s.hasQueuedThreads())) 579 Thread.yield(); 580 assertTrue(t.isAlive()); 581 if (i % 2 == 0) 582 s.release(); 583 else 584 s.release(3); 585 } 586 awaitTermination(t); 587 assertEquals(0, s.availablePermits()); 588 assertTrue(millisElapsedSince(startTime) < LONG_DELAY_MS); 589 } 590 591 /** 592 * fair locks are strictly FIFO 593 */ 594 public void testFairLocksFifo() { 595 final PublicSemaphore s = new PublicSemaphore(1, true); 596 final CountDownLatch pleaseRelease = new CountDownLatch(1); 597 Thread t1 = newStartedThread(new CheckedRunnable() { 598 public void realRun() throws InterruptedException { 599 // Will block; permits are available, but not three 600 s.acquire(3); 601 }}); 602 603 waitForQueuedThread(s, t1); 604 605 Thread t2 = newStartedThread(new CheckedRunnable() { 606 public void realRun() throws InterruptedException { 607 // Will fail, even though 1 permit is available 608 assertFalse(s.tryAcquire(0L, MILLISECONDS)); 609 assertFalse(s.tryAcquire(1, 0L, MILLISECONDS)); 610 611 // untimed tryAcquire will barge and succeed 612 assertTrue(s.tryAcquire()); 613 s.release(2); 614 assertTrue(s.tryAcquire(2)); 615 s.release(); 616 617 pleaseRelease.countDown(); 618 // Will queue up behind t1, even though 1 permit is available 619 s.acquire(); 620 }}); 621 622 await(pleaseRelease); 623 waitForQueuedThread(s, t2); 624 s.release(2); 625 awaitTermination(t1); 626 assertTrue(t2.isAlive()); 627 s.release(); 628 awaitTermination(t2); 629 } 630 631 /** 632 * toString indicates current number of permits 633 */ 634 public void testToString() { testToString(false); } 635 public void testToString_fair() { testToString(true); } 636 public void testToString(boolean fair) { 637 PublicSemaphore s = new PublicSemaphore(0, fair); 638 assertTrue(s.toString().contains("Permits = 0")); 639 s.release(); 640 assertTrue(s.toString().contains("Permits = 1")); 641 s.release(2); 642 assertTrue(s.toString().contains("Permits = 3")); 643 s.reducePermits(5); 644 assertTrue(s.toString().contains("Permits = -2")); 645 } 646 647 } 648