code: // from gee.cs.oswego.edu/home/jsr166/jsr166
  
  package jsr166tests.jtreg.util.concurrent.Semaphore;
  
  /*
   * 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
   */
  
  /*
   * @test
   * @bug 6801020 6803402
   * @summary Try to tickle race conditions in
   * AbstractQueuedSynchronizer "shared" code
   */
  
  import java.util.concurrent.Semaphore;
  
  public class RacingReleases {
  
      /** Increase this for better chance of tickling races */
      static final int iterations = 1000;
  
      public static void test(final boolean fair,
                              final boolean interruptibly)
          throws Throwable {
          for (int i = 0; i < iterations; i++) {
              final Semaphore sem = new Semaphore(0, fair);
              final Throwable[] badness = new Throwable[1];
              Runnable blocker = interruptibly ?
                  new Runnable() {
                      public void run() {
                          try {
                              sem.acquire();
                          } catch (Throwable t) {
                              badness[0] = t;
                              throw new Error(t);
                          }}}
                  :
                  new Runnable() {
                      public void run() {
                          try {
                              sem.acquireUninterruptibly();
                          } catch (Throwable t) {
                              badness[0] = t;
                              throw new Error(t);
                          }}};
  
              Thread b1 = new Thread(blocker);
              Thread b2 = new Thread(blocker);
              Runnable signaller = new Runnable() {
                  public void run() {
                      try {
                          sem.release();
                      } catch (Throwable t) {
                          badness[0] = t;
                          throw new Error(t);
                      }}};
              Thread s1 = new Thread(signaller);
              Thread s2 = new Thread(signaller);
              Thread[] threads = { b1, b2, s1, s2 };
              java.util.Collections.shuffle(java.util.Arrays.asList(threads));
              for (Thread thread : threads)
                  thread.start();
              for (Thread thread : threads) {
                  thread.join(60 * 1000);
                  if (thread.isAlive())
                      throw new Error
                          (String.format
                           ("Semaphore stuck: permits %d, thread waiting %s%n",
                            sem.availablePermits(),
                            sem.hasQueuedThreads() ? "true" : "false"));
              }
              if (badness[0] != null)
                  throw new Error(badness[0]);
              if (sem.availablePermits() != 0)
                throw new Error(String.valueOf(sem.availablePermits()));
              if (sem.hasQueuedThreads())
                throw new Error(String.valueOf(sem.hasQueuedThreads()));
              if (sem.getQueueLength() != 0)
                throw new Error(String.valueOf(sem.getQueueLength()));
              if (sem.isFair() != fair)
                throw new Error(String.valueOf(sem.isFair()));
          }
      }
  
      public static void main(String[] args) throws Throwable {
          for (boolean fair : new boolean[] { true, false })
              for (boolean interruptibly : new boolean[] { true, false })
                  test(fair, interruptibly);
      }
  }
  