| /* |
| * Written by Doug Lea with assistance from members of JCP JSR-166 |
| * Expert Group and released to the public domain, as explained at |
| * http://creativecommons.org/licenses/publicdomain |
| * Other contributors include Andrew Wright, Jeffrey Hayes, |
| * Pat Fisher, Mike Judd. |
| */ |
| |
| import junit.framework.*; |
| import java.util.*; |
| import java.util.concurrent.*; |
| import java.io.*; |
| |
| public class SemaphoreTest extends JSR166TestCase { |
| public static void main(String[] args) { |
| junit.textui.TestRunner.run (suite()); |
| } |
| public static Test suite() { |
| return new TestSuite(SemaphoreTest.class); |
| } |
| |
| /** |
| * Subclass to expose protected methods |
| */ |
| static class PublicSemaphore extends Semaphore { |
| PublicSemaphore(int p, boolean f) { super(p, f); } |
| public Collection<Thread> getQueuedThreads() { |
| return super.getQueuedThreads(); |
| } |
| public void reducePermits(int p) { |
| super.reducePermits(p); |
| } |
| } |
| |
| /** |
| * A runnable calling acquire |
| */ |
| class InterruptibleLockRunnable implements Runnable { |
| final Semaphore lock; |
| InterruptibleLockRunnable(Semaphore l) { lock = l; } |
| public void run() { |
| try { |
| lock.acquire(); |
| } catch(InterruptedException success){} |
| } |
| } |
| |
| |
| /** |
| * A runnable calling acquire that expects to be |
| * interrupted |
| */ |
| class InterruptedLockRunnable implements Runnable { |
| final Semaphore lock; |
| InterruptedLockRunnable(Semaphore l) { lock = l; } |
| public void run() { |
| try { |
| lock.acquire(); |
| threadShouldThrow(); |
| } catch(InterruptedException success){} |
| } |
| } |
| |
| /** |
| * Zero, negative, and positive initial values are allowed in constructor |
| */ |
| public void testConstructor() { |
| Semaphore s0 = new Semaphore(0, false); |
| assertEquals(0, s0.availablePermits()); |
| assertFalse(s0.isFair()); |
| Semaphore s1 = new Semaphore(-1, false); |
| assertEquals(-1, s1.availablePermits()); |
| assertFalse(s1.isFair()); |
| Semaphore s2 = new Semaphore(-1, false); |
| assertEquals(-1, s2.availablePermits()); |
| assertFalse(s2.isFair()); |
| } |
| |
| /** |
| * Constructor without fairness argument behaves as nonfair |
| */ |
| public void testConstructor2() { |
| Semaphore s0 = new Semaphore(0); |
| assertEquals(0, s0.availablePermits()); |
| assertFalse(s0.isFair()); |
| Semaphore s1 = new Semaphore(-1); |
| assertEquals(-1, s1.availablePermits()); |
| assertFalse(s1.isFair()); |
| Semaphore s2 = new Semaphore(-1); |
| assertEquals(-1, s2.availablePermits()); |
| assertFalse(s2.isFair()); |
| } |
| |
| /** |
| * tryAcquire succeeds when sufficient permits, else fails |
| */ |
| public void testTryAcquireInSameThread() { |
| Semaphore s = new Semaphore(2, false); |
| assertEquals(2, s.availablePermits()); |
| assertTrue(s.tryAcquire()); |
| assertTrue(s.tryAcquire()); |
| assertEquals(0, s.availablePermits()); |
| assertFalse(s.tryAcquire()); |
| } |
| |
| /** |
| * Acquire and release of semaphore succeed if initially available |
| */ |
| public void testAcquireReleaseInSameThread() { |
| Semaphore s = new Semaphore(1, false); |
| try { |
| s.acquire(); |
| s.release(); |
| s.acquire(); |
| s.release(); |
| s.acquire(); |
| s.release(); |
| s.acquire(); |
| s.release(); |
| s.acquire(); |
| s.release(); |
| assertEquals(1, s.availablePermits()); |
| } catch( InterruptedException e){ |
| unexpectedException(); |
| } |
| } |
| |
| /** |
| * Uninterruptible acquire and release of semaphore succeed if |
| * initially available |
| */ |
| public void testAcquireUninterruptiblyReleaseInSameThread() { |
| Semaphore s = new Semaphore(1, false); |
| try { |
| s.acquireUninterruptibly(); |
| s.release(); |
| s.acquireUninterruptibly(); |
| s.release(); |
| s.acquireUninterruptibly(); |
| s.release(); |
| s.acquireUninterruptibly(); |
| s.release(); |
| s.acquireUninterruptibly(); |
| s.release(); |
| assertEquals(1, s.availablePermits()); |
| } finally { |
| } |
| } |
| |
| /** |
| * Timed Acquire and release of semaphore succeed if |
| * initially available |
| */ |
| public void testTimedAcquireReleaseInSameThread() { |
| Semaphore s = new Semaphore(1, false); |
| try { |
| assertTrue(s.tryAcquire(SHORT_DELAY_MS, TimeUnit.MILLISECONDS)); |
| s.release(); |
| assertTrue(s.tryAcquire(SHORT_DELAY_MS, TimeUnit.MILLISECONDS)); |
| s.release(); |
| assertTrue(s.tryAcquire(SHORT_DELAY_MS, TimeUnit.MILLISECONDS)); |
| s.release(); |
| assertTrue(s.tryAcquire(SHORT_DELAY_MS, TimeUnit.MILLISECONDS)); |
| s.release(); |
| assertTrue(s.tryAcquire(SHORT_DELAY_MS, TimeUnit.MILLISECONDS)); |
| s.release(); |
| assertEquals(1, s.availablePermits()); |
| } catch( InterruptedException e){ |
| unexpectedException(); |
| } |
| } |
| |
| /** |
| * A release in one thread enables an acquire in another thread |
| */ |
| public void testAcquireReleaseInDifferentThreads() { |
| final Semaphore s = new Semaphore(0, false); |
| Thread t = new Thread(new Runnable() { |
| public void run() { |
| try { |
| s.acquire(); |
| s.release(); |
| s.release(); |
| s.acquire(); |
| } catch(InterruptedException ie){ |
| threadUnexpectedException(); |
| } |
| } |
| }); |
| try { |
| t.start(); |
| Thread.sleep(SHORT_DELAY_MS); |
| s.release(); |
| s.release(); |
| s.acquire(); |
| s.acquire(); |
| s.release(); |
| t.join(); |
| } catch( InterruptedException e){ |
| unexpectedException(); |
| } |
| } |
| |
| /** |
| * A release in one thread enables an uninterruptible acquire in another thread |
| */ |
| public void testUninterruptibleAcquireReleaseInDifferentThreads() { |
| final Semaphore s = new Semaphore(0, false); |
| Thread t = new Thread(new Runnable() { |
| public void run() { |
| s.acquireUninterruptibly(); |
| s.release(); |
| s.release(); |
| s.acquireUninterruptibly(); |
| } |
| }); |
| try { |
| t.start(); |
| Thread.sleep(SHORT_DELAY_MS); |
| s.release(); |
| s.release(); |
| s.acquireUninterruptibly(); |
| s.acquireUninterruptibly(); |
| s.release(); |
| t.join(); |
| } catch( InterruptedException e){ |
| unexpectedException(); |
| } |
| } |
| |
| |
| /** |
| * A release in one thread enables a timed acquire in another thread |
| */ |
| public void testTimedAcquireReleaseInDifferentThreads() { |
| final Semaphore s = new Semaphore(1, false); |
| Thread t = new Thread(new Runnable() { |
| public void run() { |
| try { |
| s.release(); |
| threadAssertTrue(s.tryAcquire(SHORT_DELAY_MS, TimeUnit.MILLISECONDS)); |
| s.release(); |
| threadAssertTrue(s.tryAcquire(SHORT_DELAY_MS, TimeUnit.MILLISECONDS)); |
| |
| } catch(InterruptedException ie){ |
| threadUnexpectedException(); |
| } |
| } |
| }); |
| try { |
| t.start(); |
| assertTrue(s.tryAcquire(SHORT_DELAY_MS, TimeUnit.MILLISECONDS)); |
| s.release(); |
| assertTrue(s.tryAcquire(SHORT_DELAY_MS, TimeUnit.MILLISECONDS)); |
| s.release(); |
| s.release(); |
| t.join(); |
| } catch( InterruptedException e){ |
| unexpectedException(); |
| } |
| } |
| |
| /** |
| * A waiting acquire blocks interruptibly |
| */ |
| public void testAcquire_InterruptedException() { |
| final Semaphore s = new Semaphore(0, false); |
| Thread t = new Thread(new Runnable() { |
| public void run() { |
| try { |
| s.acquire(); |
| threadShouldThrow(); |
| } catch(InterruptedException success){} |
| } |
| }); |
| t.start(); |
| try { |
| Thread.sleep(SHORT_DELAY_MS); |
| t.interrupt(); |
| t.join(); |
| } catch(InterruptedException e){ |
| unexpectedException(); |
| } |
| } |
| |
| /** |
| * A waiting timed acquire blocks interruptibly |
| */ |
| public void testTryAcquire_InterruptedException() { |
| final Semaphore s = new Semaphore(0, false); |
| Thread t = new Thread(new Runnable() { |
| public void run() { |
| try { |
| s.tryAcquire(MEDIUM_DELAY_MS, TimeUnit.MILLISECONDS); |
| threadShouldThrow(); |
| } catch(InterruptedException success){ |
| } |
| } |
| }); |
| t.start(); |
| try { |
| Thread.sleep(SHORT_DELAY_MS); |
| t.interrupt(); |
| t.join(); |
| } catch(InterruptedException e){ |
| unexpectedException(); |
| } |
| } |
| |
| /** |
| * hasQueuedThreads reports whether there are waiting threads |
| */ |
| public void testHasQueuedThreads() { |
| final Semaphore lock = new Semaphore(1, false); |
| Thread t1 = new Thread(new InterruptedLockRunnable(lock)); |
| Thread t2 = new Thread(new InterruptibleLockRunnable(lock)); |
| try { |
| assertFalse(lock.hasQueuedThreads()); |
| lock.acquireUninterruptibly(); |
| t1.start(); |
| Thread.sleep(SHORT_DELAY_MS); |
| assertTrue(lock.hasQueuedThreads()); |
| t2.start(); |
| Thread.sleep(SHORT_DELAY_MS); |
| assertTrue(lock.hasQueuedThreads()); |
| t1.interrupt(); |
| Thread.sleep(SHORT_DELAY_MS); |
| assertTrue(lock.hasQueuedThreads()); |
| lock.release(); |
| Thread.sleep(SHORT_DELAY_MS); |
| assertFalse(lock.hasQueuedThreads()); |
| t1.join(); |
| t2.join(); |
| } catch(Exception e){ |
| unexpectedException(); |
| } |
| } |
| |
| /** |
| * getQueueLength reports number of waiting threads |
| */ |
| public void testGetQueueLength() { |
| final Semaphore lock = new Semaphore(1, false); |
| Thread t1 = new Thread(new InterruptedLockRunnable(lock)); |
| Thread t2 = new Thread(new InterruptibleLockRunnable(lock)); |
| try { |
| assertEquals(0, lock.getQueueLength()); |
| lock.acquireUninterruptibly(); |
| t1.start(); |
| Thread.sleep(SHORT_DELAY_MS); |
| assertEquals(1, lock.getQueueLength()); |
| t2.start(); |
| Thread.sleep(SHORT_DELAY_MS); |
| assertEquals(2, lock.getQueueLength()); |
| t1.interrupt(); |
| Thread.sleep(SHORT_DELAY_MS); |
| assertEquals(1, lock.getQueueLength()); |
| lock.release(); |
| Thread.sleep(SHORT_DELAY_MS); |
| assertEquals(0, lock.getQueueLength()); |
| t1.join(); |
| t2.join(); |
| } catch(Exception e){ |
| unexpectedException(); |
| } |
| } |
| |
| /** |
| * getQueuedThreads includes waiting threads |
| */ |
| public void testGetQueuedThreads() { |
| final PublicSemaphore lock = new PublicSemaphore(1, false); |
| Thread t1 = new Thread(new InterruptedLockRunnable(lock)); |
| Thread t2 = new Thread(new InterruptibleLockRunnable(lock)); |
| try { |
| assertTrue(lock.getQueuedThreads().isEmpty()); |
| lock.acquireUninterruptibly(); |
| assertTrue(lock.getQueuedThreads().isEmpty()); |
| t1.start(); |
| Thread.sleep(SHORT_DELAY_MS); |
| assertTrue(lock.getQueuedThreads().contains(t1)); |
| t2.start(); |
| Thread.sleep(SHORT_DELAY_MS); |
| assertTrue(lock.getQueuedThreads().contains(t1)); |
| assertTrue(lock.getQueuedThreads().contains(t2)); |
| t1.interrupt(); |
| Thread.sleep(SHORT_DELAY_MS); |
| assertFalse(lock.getQueuedThreads().contains(t1)); |
| assertTrue(lock.getQueuedThreads().contains(t2)); |
| lock.release(); |
| Thread.sleep(SHORT_DELAY_MS); |
| assertTrue(lock.getQueuedThreads().isEmpty()); |
| t1.join(); |
| t2.join(); |
| } catch(Exception e){ |
| unexpectedException(); |
| } |
| } |
| |
| /** |
| * drainPermits reports and removes given number of permits |
| */ |
| public void testDrainPermits() { |
| Semaphore s = new Semaphore(0, false); |
| assertEquals(0, s.availablePermits()); |
| assertEquals(0, s.drainPermits()); |
| s.release(10); |
| assertEquals(10, s.availablePermits()); |
| assertEquals(10, s.drainPermits()); |
| assertEquals(0, s.availablePermits()); |
| assertEquals(0, s.drainPermits()); |
| } |
| |
| /** |
| * reducePermits reduces number of permits |
| */ |
| public void testReducePermits() { |
| PublicSemaphore s = new PublicSemaphore(10, false); |
| assertEquals(10, s.availablePermits()); |
| s.reducePermits(1); |
| assertEquals(9, s.availablePermits()); |
| s.reducePermits(10); |
| assertEquals(-1, s.availablePermits()); |
| } |
| |
| /** |
| * a deserialized serialized semaphore has same number of permits |
| */ |
| public void testSerialization() { |
| Semaphore l = new Semaphore(3, false); |
| try { |
| l.acquire(); |
| l.release(); |
| ByteArrayOutputStream bout = new ByteArrayOutputStream(10000); |
| ObjectOutputStream out = new ObjectOutputStream(new BufferedOutputStream(bout)); |
| out.writeObject(l); |
| out.close(); |
| |
| ByteArrayInputStream bin = new ByteArrayInputStream(bout.toByteArray()); |
| ObjectInputStream in = new ObjectInputStream(new BufferedInputStream(bin)); |
| Semaphore r = (Semaphore) in.readObject(); |
| assertEquals(3, r.availablePermits()); |
| assertFalse(r.isFair()); |
| r.acquire(); |
| r.release(); |
| } catch(Exception e){ |
| unexpectedException(); |
| } |
| } |
| |
| |
| /** |
| * Zero, negative, and positive initial values are allowed in constructor |
| */ |
| public void testConstructor_fair() { |
| Semaphore s0 = new Semaphore(0, true); |
| assertEquals(0, s0.availablePermits()); |
| assertTrue(s0.isFair()); |
| Semaphore s1 = new Semaphore(-1, true); |
| assertEquals(-1, s1.availablePermits()); |
| Semaphore s2 = new Semaphore(-1, true); |
| assertEquals(-1, s2.availablePermits()); |
| } |
| |
| /** |
| * tryAcquire succeeds when sufficient permits, else fails |
| */ |
| public void testTryAcquireInSameThread_fair() { |
| Semaphore s = new Semaphore(2, true); |
| assertEquals(2, s.availablePermits()); |
| assertTrue(s.tryAcquire()); |
| assertTrue(s.tryAcquire()); |
| assertEquals(0, s.availablePermits()); |
| assertFalse(s.tryAcquire()); |
| } |
| |
| /** |
| * tryAcquire(n) succeeds when sufficient permits, else fails |
| */ |
| public void testTryAcquireNInSameThread_fair() { |
| Semaphore s = new Semaphore(2, true); |
| assertEquals(2, s.availablePermits()); |
| assertTrue(s.tryAcquire(2)); |
| assertEquals(0, s.availablePermits()); |
| assertFalse(s.tryAcquire()); |
| } |
| |
| /** |
| * Acquire and release of semaphore succeed if initially available |
| */ |
| public void testAcquireReleaseInSameThread_fair() { |
| Semaphore s = new Semaphore(1, true); |
| try { |
| s.acquire(); |
| s.release(); |
| s.acquire(); |
| s.release(); |
| s.acquire(); |
| s.release(); |
| s.acquire(); |
| s.release(); |
| s.acquire(); |
| s.release(); |
| assertEquals(1, s.availablePermits()); |
| } catch( InterruptedException e){ |
| unexpectedException(); |
| } |
| } |
| |
| /** |
| * Acquire(n) and release(n) of semaphore succeed if initially available |
| */ |
| public void testAcquireReleaseNInSameThread_fair() { |
| Semaphore s = new Semaphore(1, true); |
| try { |
| s.release(1); |
| s.acquire(1); |
| s.release(2); |
| s.acquire(2); |
| s.release(3); |
| s.acquire(3); |
| s.release(4); |
| s.acquire(4); |
| s.release(5); |
| s.acquire(5); |
| assertEquals(1, s.availablePermits()); |
| } catch( InterruptedException e){ |
| unexpectedException(); |
| } |
| } |
| |
| /** |
| * Acquire(n) and release(n) of semaphore succeed if initially available |
| */ |
| public void testAcquireUninterruptiblyReleaseNInSameThread_fair() { |
| Semaphore s = new Semaphore(1, true); |
| try { |
| s.release(1); |
| s.acquireUninterruptibly(1); |
| s.release(2); |
| s.acquireUninterruptibly(2); |
| s.release(3); |
| s.acquireUninterruptibly(3); |
| s.release(4); |
| s.acquireUninterruptibly(4); |
| s.release(5); |
| s.acquireUninterruptibly(5); |
| assertEquals(1, s.availablePermits()); |
| } finally { |
| } |
| } |
| |
| /** |
| * release(n) in one thread enables timed acquire(n) in another thread |
| */ |
| public void testTimedAcquireReleaseNInSameThread_fair() { |
| Semaphore s = new Semaphore(1, true); |
| try { |
| s.release(1); |
| assertTrue(s.tryAcquire(1, SHORT_DELAY_MS, TimeUnit.MILLISECONDS)); |
| s.release(2); |
| assertTrue(s.tryAcquire(2, SHORT_DELAY_MS, TimeUnit.MILLISECONDS)); |
| s.release(3); |
| assertTrue(s.tryAcquire(3, SHORT_DELAY_MS, TimeUnit.MILLISECONDS)); |
| s.release(4); |
| assertTrue(s.tryAcquire(4, SHORT_DELAY_MS, TimeUnit.MILLISECONDS)); |
| s.release(5); |
| assertTrue(s.tryAcquire(5, SHORT_DELAY_MS, TimeUnit.MILLISECONDS)); |
| assertEquals(1, s.availablePermits()); |
| } catch( InterruptedException e){ |
| unexpectedException(); |
| } |
| } |
| |
| /** |
| * release in one thread enables timed acquire in another thread |
| */ |
| public void testTimedAcquireReleaseInSameThread_fair() { |
| Semaphore s = new Semaphore(1, true); |
| try { |
| assertTrue(s.tryAcquire(SHORT_DELAY_MS, TimeUnit.MILLISECONDS)); |
| s.release(); |
| assertTrue(s.tryAcquire(SHORT_DELAY_MS, TimeUnit.MILLISECONDS)); |
| s.release(); |
| assertTrue(s.tryAcquire(SHORT_DELAY_MS, TimeUnit.MILLISECONDS)); |
| s.release(); |
| assertTrue(s.tryAcquire(SHORT_DELAY_MS, TimeUnit.MILLISECONDS)); |
| s.release(); |
| assertTrue(s.tryAcquire(SHORT_DELAY_MS, TimeUnit.MILLISECONDS)); |
| s.release(); |
| assertEquals(1, s.availablePermits()); |
| } catch( InterruptedException e){ |
| unexpectedException(); |
| } |
| } |
| |
| /** |
| * A release in one thread enables an acquire in another thread |
| */ |
| public void testAcquireReleaseInDifferentThreads_fair() { |
| final Semaphore s = new Semaphore(0, true); |
| Thread t = new Thread(new Runnable() { |
| public void run() { |
| try { |
| s.acquire(); |
| s.acquire(); |
| s.acquire(); |
| s.acquire(); |
| } catch(InterruptedException ie){ |
| threadUnexpectedException(); |
| } |
| } |
| }); |
| try { |
| t.start(); |
| Thread.sleep(SHORT_DELAY_MS); |
| s.release(); |
| s.release(); |
| s.release(); |
| s.release(); |
| s.release(); |
| s.release(); |
| t.join(); |
| assertEquals(2, s.availablePermits()); |
| } catch( InterruptedException e){ |
| unexpectedException(); |
| } |
| } |
| |
| /** |
| * release(n) in one thread enables acquire(n) in another thread |
| */ |
| public void testAcquireReleaseNInDifferentThreads_fair() { |
| final Semaphore s = new Semaphore(0, true); |
| Thread t = new Thread(new Runnable() { |
| public void run() { |
| try { |
| s.acquire(); |
| s.release(2); |
| s.acquire(); |
| } catch(InterruptedException ie){ |
| threadUnexpectedException(); |
| } |
| } |
| }); |
| try { |
| t.start(); |
| Thread.sleep(SHORT_DELAY_MS); |
| s.release(2); |
| s.acquire(2); |
| s.release(1); |
| t.join(); |
| } catch( InterruptedException e){ |
| unexpectedException(); |
| } |
| } |
| |
| /** |
| * release(n) in one thread enables acquire(n) in another thread |
| */ |
| public void testAcquireReleaseNInDifferentThreads_fair2() { |
| final Semaphore s = new Semaphore(0, true); |
| Thread t = new Thread(new Runnable() { |
| public void run() { |
| try { |
| s.acquire(2); |
| s.acquire(2); |
| s.release(4); |
| } catch(InterruptedException ie){ |
| threadUnexpectedException(); |
| } |
| } |
| }); |
| try { |
| t.start(); |
| Thread.sleep(SHORT_DELAY_MS); |
| s.release(6); |
| s.acquire(2); |
| s.acquire(2); |
| s.release(2); |
| t.join(); |
| } catch( InterruptedException e){ |
| unexpectedException(); |
| } |
| } |
| |
| |
| |
| |
| |
| /** |
| * release in one thread enables timed acquire in another thread |
| */ |
| public void testTimedAcquireReleaseInDifferentThreads_fair() { |
| final Semaphore s = new Semaphore(1, true); |
| Thread t = new Thread(new Runnable() { |
| public void run() { |
| try { |
| threadAssertTrue(s.tryAcquire(SHORT_DELAY_MS, TimeUnit.MILLISECONDS)); |
| threadAssertTrue(s.tryAcquire(SHORT_DELAY_MS, TimeUnit.MILLISECONDS)); |
| threadAssertTrue(s.tryAcquire(SHORT_DELAY_MS, TimeUnit.MILLISECONDS)); |
| threadAssertTrue(s.tryAcquire(SHORT_DELAY_MS, TimeUnit.MILLISECONDS)); |
| threadAssertTrue(s.tryAcquire(SHORT_DELAY_MS, TimeUnit.MILLISECONDS)); |
| |
| } catch(InterruptedException ie){ |
| threadUnexpectedException(); |
| } |
| } |
| }); |
| t.start(); |
| try { |
| s.release(); |
| s.release(); |
| s.release(); |
| s.release(); |
| s.release(); |
| t.join(); |
| } catch( InterruptedException e){ |
| unexpectedException(); |
| } |
| } |
| |
| /** |
| * release(n) in one thread enables timed acquire(n) in another thread |
| */ |
| public void testTimedAcquireReleaseNInDifferentThreads_fair() { |
| final Semaphore s = new Semaphore(2, true); |
| Thread t = new Thread(new Runnable() { |
| public void run() { |
| try { |
| threadAssertTrue(s.tryAcquire(2, SHORT_DELAY_MS, TimeUnit.MILLISECONDS)); |
| s.release(2); |
| threadAssertTrue(s.tryAcquire(2, SHORT_DELAY_MS, TimeUnit.MILLISECONDS)); |
| s.release(2); |
| } catch(InterruptedException ie){ |
| threadUnexpectedException(); |
| } |
| } |
| }); |
| t.start(); |
| try { |
| assertTrue(s.tryAcquire(2, SHORT_DELAY_MS, TimeUnit.MILLISECONDS)); |
| s.release(2); |
| assertTrue(s.tryAcquire(2, SHORT_DELAY_MS, TimeUnit.MILLISECONDS)); |
| s.release(2); |
| t.join(); |
| } catch( InterruptedException e){ |
| unexpectedException(); |
| } |
| } |
| |
| /** |
| * A waiting acquire blocks interruptibly |
| */ |
| public void testAcquire_InterruptedException_fair() { |
| final Semaphore s = new Semaphore(0, true); |
| Thread t = new Thread(new Runnable() { |
| public void run() { |
| try { |
| s.acquire(); |
| threadShouldThrow(); |
| } catch(InterruptedException success){} |
| } |
| }); |
| t.start(); |
| try { |
| Thread.sleep(SHORT_DELAY_MS); |
| t.interrupt(); |
| t.join(); |
| } catch(InterruptedException e){ |
| unexpectedException(); |
| } |
| } |
| |
| /** |
| * A waiting acquire(n) blocks interruptibly |
| */ |
| public void testAcquireN_InterruptedException_fair() { |
| final Semaphore s = new Semaphore(2, true); |
| Thread t = new Thread(new Runnable() { |
| public void run() { |
| try { |
| s.acquire(3); |
| threadShouldThrow(); |
| } catch(InterruptedException success){} |
| } |
| }); |
| t.start(); |
| try { |
| Thread.sleep(SHORT_DELAY_MS); |
| t.interrupt(); |
| t.join(); |
| } catch(InterruptedException e){ |
| unexpectedException(); |
| } |
| } |
| |
| /** |
| * A waiting tryAcquire blocks interruptibly |
| */ |
| public void testTryAcquire_InterruptedException_fair() { |
| final Semaphore s = new Semaphore(0, true); |
| Thread t = new Thread(new Runnable() { |
| public void run() { |
| try { |
| s.tryAcquire(MEDIUM_DELAY_MS, TimeUnit.MILLISECONDS); |
| threadShouldThrow(); |
| } catch(InterruptedException success){ |
| } |
| } |
| }); |
| t.start(); |
| try { |
| Thread.sleep(SHORT_DELAY_MS); |
| t.interrupt(); |
| t.join(); |
| } catch(InterruptedException e){ |
| unexpectedException(); |
| } |
| } |
| |
| /** |
| * A waiting tryAcquire(n) blocks interruptibly |
| */ |
| public void testTryAcquireN_InterruptedException_fair() { |
| final Semaphore s = new Semaphore(1, true); |
| Thread t = new Thread(new Runnable() { |
| public void run() { |
| try { |
| s.tryAcquire(4, MEDIUM_DELAY_MS, TimeUnit.MILLISECONDS); |
| threadShouldThrow(); |
| } catch(InterruptedException success){ |
| } |
| } |
| }); |
| t.start(); |
| try { |
| Thread.sleep(SHORT_DELAY_MS); |
| t.interrupt(); |
| t.join(); |
| } catch(InterruptedException e){ |
| unexpectedException(); |
| } |
| } |
| |
| /** |
| * getQueueLength reports number of waiting threads |
| */ |
| public void testGetQueueLength_fair() { |
| final Semaphore lock = new Semaphore(1, true); |
| Thread t1 = new Thread(new InterruptedLockRunnable(lock)); |
| Thread t2 = new Thread(new InterruptibleLockRunnable(lock)); |
| try { |
| assertEquals(0, lock.getQueueLength()); |
| lock.acquireUninterruptibly(); |
| t1.start(); |
| Thread.sleep(SHORT_DELAY_MS); |
| assertEquals(1, lock.getQueueLength()); |
| t2.start(); |
| Thread.sleep(SHORT_DELAY_MS); |
| assertEquals(2, lock.getQueueLength()); |
| t1.interrupt(); |
| Thread.sleep(SHORT_DELAY_MS); |
| assertEquals(1, lock.getQueueLength()); |
| lock.release(); |
| Thread.sleep(SHORT_DELAY_MS); |
| assertEquals(0, lock.getQueueLength()); |
| t1.join(); |
| t2.join(); |
| } catch(Exception e){ |
| unexpectedException(); |
| } |
| } |
| |
| |
| /** |
| * a deserialized serialized semaphore has same number of permits |
| */ |
| public void testSerialization_fair() { |
| Semaphore l = new Semaphore(3, true); |
| |
| try { |
| l.acquire(); |
| l.release(); |
| ByteArrayOutputStream bout = new ByteArrayOutputStream(10000); |
| ObjectOutputStream out = new ObjectOutputStream(new BufferedOutputStream(bout)); |
| out.writeObject(l); |
| out.close(); |
| |
| ByteArrayInputStream bin = new ByteArrayInputStream(bout.toByteArray()); |
| ObjectInputStream in = new ObjectInputStream(new BufferedInputStream(bin)); |
| Semaphore r = (Semaphore) in.readObject(); |
| assertEquals(3, r.availablePermits()); |
| assertTrue(r.isFair()); |
| r.acquire(); |
| r.release(); |
| } catch(Exception e){ |
| unexpectedException(); |
| } |
| } |
| |
| /** |
| * toString indicates current number of permits |
| */ |
| public void testToString() { |
| Semaphore s = new Semaphore(0); |
| String us = s.toString(); |
| assertTrue(us.indexOf("Permits = 0") >= 0); |
| s.release(); |
| String s1 = s.toString(); |
| assertTrue(s1.indexOf("Permits = 1") >= 0); |
| s.release(); |
| String s2 = s.toString(); |
| assertTrue(s2.indexOf("Permits = 2") >= 0); |
| } |
| |
| } |