United StatesChange Country, Oracle Worldwide Web Sites Communities I am a... I want to...
Bug ID: 6366811 CyclicBarrier behaviour incorrect if interruption occurs during barrier "trip"
6366811 : CyclicBarrier behaviour incorrect if interruption occurs during barrier "trip"

Details
Type:
Bug
Submit Date:
2005-12-23
Status:
Closed
Updated Date:
2010-04-04
Project Name:
JDK
Resolved Date:
2006-01-21
Component:
core-libs
OS:
generic
Sub-Component:
java.util.concurrent
CPU:
generic
Priority:
P3
Resolution:
Fixed
Affected Versions:
6
Fixed Versions:
6

Related Reports
Backport:
Relates:

Sub Tasks

Description
The CyclicBarrier specification states that it uses a "fast-fail all or none breakage model for failed synchronization attempts" (i.e attempts that are interrupted or timed-out). The current behaviour does not meet this specification. If the last thread needed at the barrier arrives and commences to "trip" the barrier, and a waiting thread is then interrupted, then if that interrupted thread encounters InterruptedException from the internal Condition.await(), it will break the barrier and rethrow the InterruptedException - which is contrary to the "all or none" breakage semantics.

Further, at the time the interrupted thread breaks the barrier, the generation of the barrier has already been advanced, so it is the next generation that gets broken by this threads actions. This means the next group of threads to wait on the barrier will fail for no obvious reason, given that a long time could elapse between uses of the barrier.

                                    

Comments
SUGGESTED FIX

--- /u/martin/ws/mustang/src/share/classes/java/util/concurrent/CyclicBarrier.java	2005-12-04 14:55:05.651137000 -0800
+++ /u/martin/ws/holmes/src/share/classes/java/util/concurrent/CyclicBarrier.java	2006-01-03 12:49:53.981494000 -0800
@@ -115,7 +115,6 @@
      */
     private static class Generation {
         boolean broken = false;
-        boolean tripped = false;
     }
 
     /** The lock for guarding barrier entry */
@@ -142,7 +141,6 @@
      */
     private void nextGeneration() {
         // signal completion of last generation
-        generation.tripped = true;
         trip.signalAll();
         // set up next generation
         count = parties;
@@ -202,14 +200,21 @@
                     else if (nanos > 0L)
                         nanos = trip.awaitNanos(nanos);
                 } catch (InterruptedException ie) {
+                    if (g == generation && ! g.broken) {
                     breakBarrier();
                     throw ie;
+		    } else {
+			// We're about to finish waiting even if we had not
+			// been interrupted, so this interrupt is deemed to
+			// "belong" to subsequent execution.
+			Thread.currentThread().interrupt();
+		    }
                 }
 
                 if (g.broken)
                     throw new BrokenBarrierException();
 
-                if (g.tripped)
+                if (g != generation)
                     return index;
 
                 if (timed && nanos <= 0L) {
@@ -270,7 +275,7 @@
      *
      * <p>If the current thread is not the last to arrive then it is
      * disabled for thread scheduling purposes and lies dormant until
-     * one of following things happens:
+     * one of the following things happens:
      * <ul>
      * <li>The last thread arrives; or
      * <li>Some other thread {@link Thread#interrupt interrupts} the current
                                     
2006-01-03
EVALUATION

Two refinements:
- the "tripped" field can be eliminated, since g.tripped is equivalent to "generation == g"
- If an InterruptedException is caught when the await would have ended for some other reason
  anyways, the interrupt bit should be set on again, and the wait ended for the other reason,
  possibly throwing BrokenBarrierException.  This leads to slightly more predictable behavior.
  (It's still not a good idea to try to break a CyclicBarrier by interrupting more than one thread)
                                     
2006-01-03
SUGGESTED FIX

When the interrupted thread catches the InterruptedException it only breaks the barrier and rethrows the IE if the current generation has not been tripped. Otherwise it simply reasserts the interrupt state of the thread.
                                     
2005-12-23
EVALUATION

This bug has been analysed and confirmed by the jsr166 EG
                                     
2005-12-23



Hardware and Software, Engineered to Work Together