test/jdk/java/util/concurrent/CyclicBarrier/Basic.java
changeset 58137 6a556bcd94fc
parent 51769 0ae80830256e
equal deleted inserted replaced
58136:f689a48dba4b 58137:6a556bcd94fc
    35 import java.util.Iterator;
    35 import java.util.Iterator;
    36 import java.util.List;
    36 import java.util.List;
    37 import java.util.concurrent.BrokenBarrierException;
    37 import java.util.concurrent.BrokenBarrierException;
    38 import java.util.concurrent.CountDownLatch;
    38 import java.util.concurrent.CountDownLatch;
    39 import java.util.concurrent.CyclicBarrier;
    39 import java.util.concurrent.CyclicBarrier;
       
    40 import java.util.concurrent.ThreadLocalRandom;
    40 import java.util.concurrent.TimeoutException;
    41 import java.util.concurrent.TimeoutException;
    41 import java.util.concurrent.atomic.AtomicInteger;
    42 import java.util.concurrent.atomic.AtomicInteger;
    42 import jdk.test.lib.Utils;
    43 import jdk.test.lib.Utils;
    43 
    44 
    44 public class Basic {
    45 public class Basic {
   291 
   292 
   292     /**
   293     /**
   293      * Handling of extra interrupts while waiting - tests for bug 6366811
   294      * Handling of extra interrupts while waiting - tests for bug 6366811
   294      */
   295      */
   295     private static void testInterrupts() {
   296     private static void testInterrupts() {
   296         final int N = 10;
   297         final int N = ThreadLocalRandom.current().nextInt(2, 10);
   297         final CyclicBarrier startingGate = new CyclicBarrier(N+1);
   298         final CyclicBarrier startingGate = new CyclicBarrier(N+1);
   298 
   299 
   299         /**
   300         /**
   300          * A version of Awaiter that also records interrupted state.
   301          * A version of Awaiter that also records interrupted state.
   301          */
   302          */
   302         class Waiter extends CheckedThread {
   303         class Waiter extends CheckedThread {
   303             private boolean timed;
   304             private final boolean timed;
   304             private CyclicBarrier barrier;
   305             private final CyclicBarrier barrier;
   305             private CountDownLatch doneSignal;
   306             private final CountDownLatch doneSignal;
   306             private Throwable throwable;
   307             volatile Throwable throwable;
   307             private boolean interrupted;
   308             volatile boolean interruptStatusSetAfterAwait;
   308 
   309 
   309             public Waiter(boolean timed,
   310             public Waiter(CountDownLatch doneSignal, CyclicBarrier barrier) {
   310                           CountDownLatch doneSignal,
   311                 this.timed = ThreadLocalRandom.current().nextBoolean();
   311                           CyclicBarrier barrier) {
       
   312                 this.timed = timed;
       
   313                 this.doneSignal = doneSignal;
   312                 this.doneSignal = doneSignal;
   314                 this.barrier = barrier;
   313                 this.barrier = barrier;
   315             }
   314             }
   316             Throwable throwable() { return this.throwable; }
   315 
   317             boolean interruptBit() { return this.interrupted; }
       
   318             void realRun() throws Throwable {
   316             void realRun() throws Throwable {
   319                 startingGate.await(LONG_DELAY_MS, MILLISECONDS);
   317                 startingGate.await(LONG_DELAY_MS, MILLISECONDS);
       
   318 
   320                 try {
   319                 try {
   321                     if (timed) barrier.await(LONG_DELAY_MS, MILLISECONDS);
   320                     if (timed) barrier.await(LONG_DELAY_MS, MILLISECONDS);
   322                     else barrier.await(); }
   321                     else barrier.await();
   323                 catch (Throwable throwable) { this.throwable = throwable; }
   322                 } catch (Throwable throwable) {
   324 
   323                     this.throwable = throwable;
   325                 try { doneSignal.await(LONG_DELAY_MS, MILLISECONDS); }
   324                 }
   326                 catch (InterruptedException e) { interrupted = true; }
   325 
       
   326                 try {
       
   327                     check(doneSignal.await(LONG_DELAY_MS, MILLISECONDS));
       
   328                     if (Thread.interrupted())
       
   329                         interruptStatusSetAfterAwait = true;
       
   330                 } catch (InterruptedException e) {
       
   331                     interruptStatusSetAfterAwait = true;
       
   332                 }
   327             }
   333             }
   328         }
   334         }
   329 
   335 
   330         //----------------------------------------------------------------
   336         //----------------------------------------------------------------
   331         // Interrupt occurs during barrier trip
   337         // Interrupt occurs during barrier trip
   350                     // seems to work reliably while yield does not.
   356                     // seems to work reliably while yield does not.
   351                     Thread.sleep(100);
   357                     Thread.sleep(100);
   352                 } catch (Throwable t) { unexpected(t); }
   358                 } catch (Throwable t) { unexpected(t); }
   353             }};
   359             }};
   354             for (int i = 0; i < N; i++) {
   360             for (int i = 0; i < N; i++) {
   355                 Waiter waiter = new Waiter(i < N/2, doneSignal, barrier);
   361                 Waiter waiter = new Waiter(doneSignal, barrier);
   356                 waiter.start();
   362                 waiter.start();
   357                 waiters.add(waiter);
   363                 waiters.add(waiter);
   358             }
   364             }
   359             startingGate.await(LONG_DELAY_MS, MILLISECONDS);
   365             startingGate.await(LONG_DELAY_MS, MILLISECONDS);
   360             while (barrier.getNumberWaiting() < N) Thread.yield();
   366             while (barrier.getNumberWaiting() < N) Thread.yield();
   361             barrier.await();
   367             barrier.await();
   362             doneSignal.countDown();
   368             doneSignal.countDown();
   363             int countInterrupted = 0;
   369             int countInterruptStatusSetAfterAwait = 0;
   364             int countInterruptedException = 0;
       
   365             int countBrokenBarrierException = 0;
       
   366             for (Waiter waiter : waiters) {
   370             for (Waiter waiter : waiters) {
   367                 waiter.join();
   371                 waiter.join();
   368                 equal(waiter.throwable(), null);
   372                 equal(waiter.throwable, null);
   369                 if (waiter.interruptBit())
   373                 if (waiter.interruptStatusSetAfterAwait)
   370                     countInterrupted++;
   374                     countInterruptStatusSetAfterAwait++;
   371             }
   375             }
   372             equal(countInterrupted, N/2);
   376             equal(countInterruptStatusSetAfterAwait, N/2);
   373             check(! barrier.isBroken());
   377             check(! barrier.isBroken());
   374         } catch (Throwable t) { unexpected(t); }
   378         } catch (Throwable t) { unexpected(t); }
   375 
   379 
   376         //----------------------------------------------------------------
   380         //----------------------------------------------------------------
   377         // Multiple interrupts occur during barrier await
   381         // Multiple interrupts occur during barrier await
   379         try {
   383         try {
   380             final CountDownLatch doneSignal = new CountDownLatch(1);
   384             final CountDownLatch doneSignal = new CountDownLatch(1);
   381             final CyclicBarrier barrier = new CyclicBarrier(N+1);
   385             final CyclicBarrier barrier = new CyclicBarrier(N+1);
   382             final List<Waiter> waiters = new ArrayList<>(N);
   386             final List<Waiter> waiters = new ArrayList<>(N);
   383             for (int i = 0; i < N; i++) {
   387             for (int i = 0; i < N; i++) {
   384                 Waiter waiter = new Waiter(i < N/2, doneSignal, barrier);
   388                 Waiter waiter = new Waiter(doneSignal, barrier);
   385                 waiter.start();
   389                 waiter.start();
   386                 waiters.add(waiter);
   390                 waiters.add(waiter);
   387             }
   391             }
   388             startingGate.await(LONG_DELAY_MS, MILLISECONDS);
   392             startingGate.await(LONG_DELAY_MS, MILLISECONDS);
   389             while (barrier.getNumberWaiting() < N) Thread.yield();
   393             while (barrier.getNumberWaiting() < N) Thread.yield();
   390             for (int i = 0; i < N/2; i++)
   394             for (int i = 0; i < N/2; i++) {
   391                 waiters.get(i).interrupt();
   395                 Thread waiter = waiters.get(i);
       
   396                 waiter.interrupt();
       
   397             }
   392             doneSignal.countDown();
   398             doneSignal.countDown();
   393             int countInterrupted = 0;
       
   394             int countInterruptedException = 0;
   399             int countInterruptedException = 0;
   395             int countBrokenBarrierException = 0;
   400             int countBrokenBarrierException = 0;
       
   401             int countInterruptStatusSetAfterAwait = 0;
   396             for (Waiter waiter : waiters) {
   402             for (Waiter waiter : waiters) {
   397                 waiter.join();
   403                 waiter.join();
   398                 if (waiter.throwable() instanceof InterruptedException)
   404                 if (waiter.throwable instanceof InterruptedException)
   399                     countInterruptedException++;
   405                     countInterruptedException++;
   400                 if (waiter.throwable() instanceof BrokenBarrierException)
   406                 if (waiter.throwable instanceof BrokenBarrierException)
   401                     countBrokenBarrierException++;
   407                     countBrokenBarrierException++;
   402                 if (waiter.interruptBit())
   408                 if (waiter.interruptStatusSetAfterAwait)
   403                     countInterrupted++;
   409                     countInterruptStatusSetAfterAwait++;
   404             }
   410             }
   405             equal(countInterrupted, N/2-1);
       
   406             equal(countInterruptedException, 1);
   411             equal(countInterruptedException, 1);
   407             equal(countBrokenBarrierException, N-1);
   412             equal(countBrokenBarrierException, N-1);
   408             checkBroken(barrier);
   413             checkBroken(barrier);
       
   414             equal(countInterruptStatusSetAfterAwait, N/2-1);
   409             reset(barrier);
   415             reset(barrier);
   410         } catch (Throwable t) { unexpected(t); }
   416         } catch (Throwable t) { unexpected(t); }
   411     }
   417     }
   412 
   418 
   413     //--------------------- Infrastructure ---------------------------
   419     //--------------------- Infrastructure ---------------------------