Uploaded image for project: 'JDK'
  1. JDK
  2. JDK-6253848

CyclicBarrier behavior incorrect if "broken" or reset

    XMLWordPrintable

    Details

    • Type: Bug
    • Status: Closed
    • Priority: P3
    • Resolution: Fixed
    • Affects Version/s: 5.0
    • Fix Version/s: 6
    • Component/s: core-libs
    • Labels:
    • Subcomponent:
    • Resolved In Build:
      b35
    • CPU:
      x86
    • OS:
      windows_xp
    • Verification:
      Verified

      Backports

        Description

        FULL PRODUCT VERSION :
        java version "1.5.0_02"
        Java(TM) 2 Runtime Environment, Standard Edition (build 1.5.0_02-b09)
        Java HotSpot(TM) Client VM (build 1.5.0_02-b09, mixed mode, sharing)

        ADDITIONAL OS VERSION INFORMATION :
        Microsoft Windows XP [Version 5.1.2600]

        A DESCRIPTION OF THE PROBLEM :
        In this seemingly appropriate usage of CyclicBarrier:

        * Create barrier with n + 1 parties: 1 for each "worker" thread, plus 1 for the current thread; and set a barrier action on it.
        1. Start n workers, which: each perform some task and then await the barrier.
        2. Have the current then thread await the barrier -- and therefore each worker, plus the barrier action.
        3. Now that await has returned in the current thread, reset the barrier and run another cycle on it as above.

        At the point when reset is called by the current thread, an arbitrary number (sometimes 0) of worker threads throw a BrokenBarrierException.

        The await method is the only way to get notice that all parties have reported and the barrier action is also complete, but it does not behave correctly: Though the await method has returned, indicating all parties and the barrier action are complete, some parties still sense the ensuing call to reset() and throw an exception as though they had not yet completed. The reset method does not synchronize itself.

        STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
        A test case is given.


        REPRODUCIBILITY :
        This bug can be reproduced always.

        ---------- BEGIN SOURCE ----------
        import java.util.concurrent.CyclicBarrier;


        public class Test {
            
            /* The number of worker threads to create: */
            private static final int WORKER_COUNT = 10;
            
            /* The barrier; with 1 party for each worker, plus the primordial thread: */
            private static final CyclicBarrier barrier
                    = new CyclicBarrier((WORKER_COUNT + 1), new BarrierAction());

            
            /** A worker thread that would work on a single element of data. */
            private static class Worker extends Thread {
                public void run() {
                    System.out.println(getName() + " Worker.run().");
                    try {
                        barrier.await();
                    }
                    catch (Exception ex) {
                        System.err.println(" Worker terminating with exception:");
                        ex.printStackTrace();
                    }
                }
            }

            
            /** The action that would coordinate each Worker thread's results. */
            private static class BarrierAction implements Runnable {
                public void run() {
                    System.out.println("BarrierAction.run().");
                }
            }


            /** Runs the test. Several iterations are performed on the barrier. */
            public static void main(final String[] args) throws Exception {
                /* Run more than 2 cycles on the barrier to increase
                 * the likelihood of seeing an exception: */
                final int BARRIER_CYCLES = 3;
                for (int i = 0; i < BARRIER_CYCLES; i++) {
                    /* Create and start workers: */
                    for (int j = 0; j < WORKER_COUNT; j++) {
                        new Worker().start();
                    }
                    
                    /* Wait for all workers (plus the barrier action) to complete: */
                    barrier.await();
                    
                    System.out.println("Barrier cycle " + i + " complete.");
                    
                    /* Reset for next cycle: */
                    barrier.reset();
                }
            }
            
        }

        ---------- END SOURCE ----------

        CUSTOMER SUBMITTED WORKAROUND :
        You may be able to use a latch instead (assuming it works correctly). Otherwise, manually synchronize the worker threads around the call to reset -- basically manually implement the barrier on your own really. Or use something tangential like a synchronized queue.
        ###@###.### 2005-04-12 09:39:06 GMT

          Attachments

            Issue Links

              Activity

                People

                Assignee:
                martin Martin Buchholz
                Reporter:
                jssunw Jitender S (Inactive)
                Votes:
                0 Vote for this issue
                Watchers:
                0 Start watching this issue

                  Dates

                  Created:
                  Updated:
                  Resolved:
                  Imported:
                  Indexed: