< prev index next >

test/jdk/java/util/concurrent/CyclicBarrier/Basic.java

Print this page
8145138: CyclicBarrier/Basic.java failed with "3 not equal to 4"
Reviewed-by: martin, alanb


  20  * or visit www.oracle.com if you need additional information or have any
  21  * questions.
  22  */
  23 
  24 /*
  25  * @test
  26  * @bug 6253848 6366811
  27  * @summary Basic tests for CyclicBarrier
  28  * @library /test/lib
  29  * @author Martin Buchholz, David Holmes
  30  */
  31 
  32 import static java.util.concurrent.TimeUnit.MILLISECONDS;
  33 
  34 import java.util.ArrayList;
  35 import java.util.Iterator;
  36 import java.util.List;
  37 import java.util.concurrent.BrokenBarrierException;
  38 import java.util.concurrent.CountDownLatch;
  39 import java.util.concurrent.CyclicBarrier;

  40 import java.util.concurrent.TimeoutException;
  41 import java.util.concurrent.atomic.AtomicInteger;
  42 import jdk.test.lib.Utils;
  43 
  44 public class Basic {
  45     static final long LONG_DELAY_MS = Utils.adjustTimeout(10_000);
  46 
  47     private static void checkBroken(final CyclicBarrier barrier) {
  48         check(barrier.isBroken());
  49         equal(barrier.getNumberWaiting(), 0);
  50 
  51         THROWS(BrokenBarrierException.class,
  52                () -> barrier.await(),
  53                () -> barrier.await(100, MILLISECONDS));
  54     }
  55 
  56     private static void reset(CyclicBarrier barrier) {
  57         barrier.reset();
  58         check(! barrier.isBroken());
  59         equal(barrier.getNumberWaiting(), 0);


 276                     barrier.await();
 277                     fail("Expected Error not thrown"); }
 278                 catch (Error e) { pass(); }
 279                 catch (Throwable t) { unexpected(t); }
 280                 a1.join();
 281                 a2.join();
 282                 checkResult(a1, BrokenBarrierException.class);
 283                 checkResult(a2, BrokenBarrierException.class);
 284                 checkBroken(barrier);
 285                 reset(barrier);
 286             }
 287         } catch (Throwable t) { unexpected(t); }
 288 
 289         testInterrupts();
 290     }
 291 
 292     /**
 293      * Handling of extra interrupts while waiting - tests for bug 6366811
 294      */
 295     private static void testInterrupts() {
 296         final int N = 10;
 297         final CyclicBarrier startingGate = new CyclicBarrier(N+1);
 298 
 299         /**
 300          * A version of Awaiter that also records interrupted state.
 301          */
 302         class Waiter extends CheckedThread {
 303             private boolean timed;
 304             private CyclicBarrier barrier;
 305             private CountDownLatch doneSignal;
 306             private Throwable throwable;
 307             private boolean interrupted;
 308 
 309             public Waiter(boolean timed,
 310                           CountDownLatch doneSignal,
 311                           CyclicBarrier barrier) {
 312                 this.timed = timed;
 313                 this.doneSignal = doneSignal;
 314                 this.barrier = barrier;
 315             }
 316             Throwable throwable() { return this.throwable; }
 317             boolean interruptBit() { return this.interrupted; }
 318             void realRun() throws Throwable {
 319                 startingGate.await(LONG_DELAY_MS, MILLISECONDS);

 320                 try {
 321                     if (timed) barrier.await(LONG_DELAY_MS, MILLISECONDS);
 322                     else barrier.await(); }
 323                 catch (Throwable throwable) { this.throwable = throwable; }


 324 
 325                 try { doneSignal.await(LONG_DELAY_MS, MILLISECONDS); }
 326                 catch (InterruptedException e) { interrupted = true; }





 327             }
 328         }
 329 
 330         //----------------------------------------------------------------
 331         // Interrupt occurs during barrier trip
 332         //----------------------------------------------------------------
 333         try {
 334             final CountDownLatch doneSignal = new CountDownLatch(1);
 335             final List<Waiter> waiters = new ArrayList<>(N);
 336 
 337             // work around finality of closed-over variables
 338             final Runnable[] realAction = new Runnable[1];
 339             final Runnable delegateAction =
 340                 new Runnable() {public void run() {realAction[0].run();}};
 341             final CyclicBarrier barrier = new CyclicBarrier(N+1, delegateAction);
 342 
 343             realAction[0] = new Runnable() { public void run() {
 344                 try {
 345                     for (int i = 0; i < N/2; i++)
 346                         waiters.get(i).interrupt();
 347                     // we need to try and ensure that the waiters get
 348                     // to process their interruption before we do the
 349                     // signalAll that trips the barrier. Using sleep
 350                     // seems to work reliably while yield does not.
 351                     Thread.sleep(100);
 352                 } catch (Throwable t) { unexpected(t); }
 353             }};
 354             for (int i = 0; i < N; i++) {
 355                 Waiter waiter = new Waiter(i < N/2, doneSignal, barrier);
 356                 waiter.start();
 357                 waiters.add(waiter);
 358             }
 359             startingGate.await(LONG_DELAY_MS, MILLISECONDS);
 360             while (barrier.getNumberWaiting() < N) Thread.yield();
 361             barrier.await();
 362             doneSignal.countDown();
 363             int countInterrupted = 0;
 364             int countInterruptedException = 0;
 365             int countBrokenBarrierException = 0;
 366             for (Waiter waiter : waiters) {
 367                 waiter.join();
 368                 equal(waiter.throwable(), null);
 369                 if (waiter.interruptBit())
 370                     countInterrupted++;
 371             }
 372             equal(countInterrupted, N/2);
 373             check(! barrier.isBroken());
 374         } catch (Throwable t) { unexpected(t); }
 375 
 376         //----------------------------------------------------------------
 377         // Multiple interrupts occur during barrier await
 378         //----------------------------------------------------------------
 379         try {
 380             final CountDownLatch doneSignal = new CountDownLatch(1);
 381             final CyclicBarrier barrier = new CyclicBarrier(N+1);
 382             final List<Waiter> waiters = new ArrayList<>(N);
 383             for (int i = 0; i < N; i++) {
 384                 Waiter waiter = new Waiter(i < N/2, doneSignal, barrier);
 385                 waiter.start();
 386                 waiters.add(waiter);
 387             }
 388             startingGate.await(LONG_DELAY_MS, MILLISECONDS);
 389             while (barrier.getNumberWaiting() < N) Thread.yield();
 390             for (int i = 0; i < N/2; i++)
 391                 waiters.get(i).interrupt();


 392             doneSignal.countDown();
 393             int countInterrupted = 0;
 394             int countInterruptedException = 0;
 395             int countBrokenBarrierException = 0;

 396             for (Waiter waiter : waiters) {
 397                 waiter.join();
 398                 if (waiter.throwable() instanceof InterruptedException)
 399                     countInterruptedException++;
 400                 if (waiter.throwable() instanceof BrokenBarrierException)
 401                     countBrokenBarrierException++;
 402                 if (waiter.interruptBit())
 403                     countInterrupted++;
 404             }
 405             equal(countInterrupted, N/2-1);
 406             equal(countInterruptedException, 1);
 407             equal(countBrokenBarrierException, N-1);
 408             checkBroken(barrier);

 409             reset(barrier);
 410         } catch (Throwable t) { unexpected(t); }
 411     }
 412 
 413     //--------------------- Infrastructure ---------------------------
 414     static volatile int passed = 0, failed = 0;
 415     static void pass() {passed++;}
 416     static void fail() {failed++; Thread.dumpStack();}
 417     static void fail(String msg) {System.out.println(msg); fail();}
 418     static void unexpected(Throwable t) {failed++; t.printStackTrace();}
 419     static void check(boolean cond) {if (cond) pass(); else fail();}
 420     static void equal(Object x, Object y) {
 421         if (x == null ? y == null : x.equals(y)) pass();
 422         else fail(x + " not equal to " + y);}
 423     public static void main(String[] args) throws Throwable {
 424         try {realMain(args);} catch (Throwable t) {unexpected(t);}
 425         System.out.printf("%nPassed = %d, failed = %d%n%n", passed, failed);
 426         if (failed > 0) throw new AssertionError("Some tests failed");}
 427     interface Fun {void f() throws Throwable;}
 428     private static void THROWS(Class<? extends Throwable> k, Fun... fs) {


  20  * or visit www.oracle.com if you need additional information or have any
  21  * questions.
  22  */
  23 
  24 /*
  25  * @test
  26  * @bug 6253848 6366811
  27  * @summary Basic tests for CyclicBarrier
  28  * @library /test/lib
  29  * @author Martin Buchholz, David Holmes
  30  */
  31 
  32 import static java.util.concurrent.TimeUnit.MILLISECONDS;
  33 
  34 import java.util.ArrayList;
  35 import java.util.Iterator;
  36 import java.util.List;
  37 import java.util.concurrent.BrokenBarrierException;
  38 import java.util.concurrent.CountDownLatch;
  39 import java.util.concurrent.CyclicBarrier;
  40 import java.util.concurrent.ThreadLocalRandom;
  41 import java.util.concurrent.TimeoutException;
  42 import java.util.concurrent.atomic.AtomicInteger;
  43 import jdk.test.lib.Utils;
  44 
  45 public class Basic {
  46     static final long LONG_DELAY_MS = Utils.adjustTimeout(10_000);
  47 
  48     private static void checkBroken(final CyclicBarrier barrier) {
  49         check(barrier.isBroken());
  50         equal(barrier.getNumberWaiting(), 0);
  51 
  52         THROWS(BrokenBarrierException.class,
  53                () -> barrier.await(),
  54                () -> barrier.await(100, MILLISECONDS));
  55     }
  56 
  57     private static void reset(CyclicBarrier barrier) {
  58         barrier.reset();
  59         check(! barrier.isBroken());
  60         equal(barrier.getNumberWaiting(), 0);


 277                     barrier.await();
 278                     fail("Expected Error not thrown"); }
 279                 catch (Error e) { pass(); }
 280                 catch (Throwable t) { unexpected(t); }
 281                 a1.join();
 282                 a2.join();
 283                 checkResult(a1, BrokenBarrierException.class);
 284                 checkResult(a2, BrokenBarrierException.class);
 285                 checkBroken(barrier);
 286                 reset(barrier);
 287             }
 288         } catch (Throwable t) { unexpected(t); }
 289 
 290         testInterrupts();
 291     }
 292 
 293     /**
 294      * Handling of extra interrupts while waiting - tests for bug 6366811
 295      */
 296     private static void testInterrupts() {
 297         final int N = ThreadLocalRandom.current().nextInt(2, 10);
 298         final CyclicBarrier startingGate = new CyclicBarrier(N+1);
 299 
 300         /**
 301          * A version of Awaiter that also records interrupted state.
 302          */
 303         class Waiter extends CheckedThread {
 304             private final boolean timed;
 305             private final CyclicBarrier barrier;
 306             private final CountDownLatch doneSignal;
 307             volatile Throwable throwable;
 308             volatile boolean interruptStatusSetAfterAwait;
 309 
 310             public Waiter(CountDownLatch doneSignal, CyclicBarrier barrier) {
 311                 this.timed = ThreadLocalRandom.current().nextBoolean();


 312                 this.doneSignal = doneSignal;
 313                 this.barrier = barrier;
 314             }
 315 

 316             void realRun() throws Throwable {
 317                 startingGate.await(LONG_DELAY_MS, MILLISECONDS);
 318 
 319                 try {
 320                     if (timed) barrier.await(LONG_DELAY_MS, MILLISECONDS);
 321                     else barrier.await();
 322                 } catch (Throwable throwable) {
 323                     this.throwable = throwable;
 324                 }
 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                 }
 333             }
 334         }
 335 
 336         //----------------------------------------------------------------
 337         // Interrupt occurs during barrier trip
 338         //----------------------------------------------------------------
 339         try {
 340             final CountDownLatch doneSignal = new CountDownLatch(1);
 341             final List<Waiter> waiters = new ArrayList<>(N);
 342 
 343             // work around finality of closed-over variables
 344             final Runnable[] realAction = new Runnable[1];
 345             final Runnable delegateAction =
 346                 new Runnable() {public void run() {realAction[0].run();}};
 347             final CyclicBarrier barrier = new CyclicBarrier(N+1, delegateAction);
 348 
 349             realAction[0] = new Runnable() { public void run() {
 350                 try {
 351                     for (int i = 0; i < N/2; i++)
 352                         waiters.get(i).interrupt();
 353                     // we need to try and ensure that the waiters get
 354                     // to process their interruption before we do the
 355                     // signalAll that trips the barrier. Using sleep
 356                     // seems to work reliably while yield does not.
 357                     Thread.sleep(100);
 358                 } catch (Throwable t) { unexpected(t); }
 359             }};
 360             for (int i = 0; i < N; i++) {
 361                 Waiter waiter = new Waiter(doneSignal, barrier);
 362                 waiter.start();
 363                 waiters.add(waiter);
 364             }
 365             startingGate.await(LONG_DELAY_MS, MILLISECONDS);
 366             while (barrier.getNumberWaiting() < N) Thread.yield();
 367             barrier.await();
 368             doneSignal.countDown();
 369             int countInterruptStatusSetAfterAwait = 0;


 370             for (Waiter waiter : waiters) {
 371                 waiter.join();
 372                 equal(waiter.throwable, null);
 373                 if (waiter.interruptStatusSetAfterAwait)
 374                     countInterruptStatusSetAfterAwait++;
 375             }
 376             equal(countInterruptStatusSetAfterAwait, N/2);
 377             check(! barrier.isBroken());
 378         } catch (Throwable t) { unexpected(t); }
 379 
 380         //----------------------------------------------------------------
 381         // Multiple interrupts occur during barrier await
 382         //----------------------------------------------------------------
 383         try {
 384             final CountDownLatch doneSignal = new CountDownLatch(1);
 385             final CyclicBarrier barrier = new CyclicBarrier(N+1);
 386             final List<Waiter> waiters = new ArrayList<>(N);
 387             for (int i = 0; i < N; i++) {
 388                 Waiter waiter = new Waiter(doneSignal, barrier);
 389                 waiter.start();
 390                 waiters.add(waiter);
 391             }
 392             startingGate.await(LONG_DELAY_MS, MILLISECONDS);
 393             while (barrier.getNumberWaiting() < N) Thread.yield();
 394             for (int i = 0; i < N/2; i++) {
 395                 Thread waiter = waiters.get(i);
 396                 waiter.interrupt();
 397             }
 398             doneSignal.countDown();

 399             int countInterruptedException = 0;
 400             int countBrokenBarrierException = 0;
 401             int countInterruptStatusSetAfterAwait = 0;
 402             for (Waiter waiter : waiters) {
 403                 waiter.join();
 404                 if (waiter.throwable instanceof InterruptedException)
 405                     countInterruptedException++;
 406                 if (waiter.throwable instanceof BrokenBarrierException)
 407                     countBrokenBarrierException++;
 408                 if (waiter.interruptStatusSetAfterAwait)
 409                     countInterruptStatusSetAfterAwait++;
 410             }

 411             equal(countInterruptedException, 1);
 412             equal(countBrokenBarrierException, N-1);
 413             checkBroken(barrier);
 414             equal(countInterruptStatusSetAfterAwait, N/2-1);
 415             reset(barrier);
 416         } catch (Throwable t) { unexpected(t); }
 417     }
 418 
 419     //--------------------- Infrastructure ---------------------------
 420     static volatile int passed = 0, failed = 0;
 421     static void pass() {passed++;}
 422     static void fail() {failed++; Thread.dumpStack();}
 423     static void fail(String msg) {System.out.println(msg); fail();}
 424     static void unexpected(Throwable t) {failed++; t.printStackTrace();}
 425     static void check(boolean cond) {if (cond) pass(); else fail();}
 426     static void equal(Object x, Object y) {
 427         if (x == null ? y == null : x.equals(y)) pass();
 428         else fail(x + " not equal to " + y);}
 429     public static void main(String[] args) throws Throwable {
 430         try {realMain(args);} catch (Throwable t) {unexpected(t);}
 431         System.out.printf("%nPassed = %d, failed = %d%n%n", passed, failed);
 432         if (failed > 0) throw new AssertionError("Some tests failed");}
 433     interface Fun {void f() throws Throwable;}
 434     private static void THROWS(Class<? extends Throwable> k, Fun... fs) {
< prev index next >