简体   繁体   中英

Deadlock with CyclicBarrier?

I have an issue with the following piece of code for CyclicBarrier.

    MyJavaCyclicBarrierExample.java:::::::

            import java.util.Date; 
            import java.util.concurrent.BrokenBarrierException; 
            import java.util.concurrent.CyclicBarrier; 

            public class MyJavaCyclicBarrierExample { 

              public static void main(String[] args) { 

                  //3 threads are part of the barrier, ServiceOne, ServiceTwo and this main thread calling them. 

                  final CyclicBarrier barrier = new CyclicBarrier(2); 
                  Thread serviceOneThread = new Thread(new ServiceOne(barrier)); 
                  Thread serviceTwoThread = new Thread(new ServiceTwo(barrier)); 

                  System.out.println("Starting both the services at "+new Date()); 

                  serviceOneThread.start(); 
                  serviceTwoThread.start(); 

                  //Lets say main also has to do some work
                  try {
                      System.out.println("Main is going to do some work....");
                      Thread.sleep(10000);
                      System.out.println("Main has finished its work....");
                } catch (InterruptedException e1) {
                    e1.printStackTrace();
                }

                  try {
                      System.out.println("Main is now going to wait at the barrier....");
                      barrier.await();
                      System.out.println("Main woken up at the barrier....");
                  } catch (InterruptedException e) { 
                      System.out.println("Main Thread interrupted!"); 
                      e.printStackTrace(); 
                  } catch (BrokenBarrierException e) { 
                      System.out.println("Main Thread interrupted!"); 
                      e.printStackTrace(); 
                  } 
                  System.out.println("Ending both the services at "+new Date()); 
              } 
            } 


        ServiceOne.java :::::::::
        import java.util.concurrent.BrokenBarrierException; 
        import java.util.concurrent.CyclicBarrier; 

        public class ServiceOne implements Runnable { 
            private final CyclicBarrier cyclicBarrier; 

            public ServiceOne(CyclicBarrier cyclicBarrier) { 
                this.cyclicBarrier = cyclicBarrier; 
            }

            @Override
            public void run() { 
                System.out.println("Starting service One..."); 
                try { 
                    Thread.sleep(3000);   //assuming service one does some business logic here...
                } catch (InterruptedException e1) { 
                    e1.printStackTrace(); 
                } 
                System.out.println("Service One has finished its work... waiting for others..."); 
                try {
                        System.out.println("ServiceOne is now going to wait at the barrier....");
                        cyclicBarrier.await();      //Let's wait for the other threads at the cyclic barrier.
                        System.out.println("ServiceOne woken up at the barrier....");
                } catch (InterruptedException e) { 
                   System.out.println("Service one interrupted!"); 
                   e.printStackTrace(); 
                } catch (BrokenBarrierException e) { 
                   System.out.println("Service one interrupted!"); 
                   e.printStackTrace(); 
                } 
                System.out.println("The wait is over, lets complete Service Two!"); 
            } 
        } 



ServiceTwo.java:::::::::

import java.util.concurrent.BrokenBarrierException; 
import java.util.concurrent.CyclicBarrier; 
public class ServiceTwo implements Runnable { 
    private final CyclicBarrier cyclicBarrier; 
    public ServiceTwo(CyclicBarrier cyclicBarrier) { 
        this.cyclicBarrier = cyclicBarrier; 
    } 
    @Override 
    public void run() { 
        System.out.println("Starting service Two...."); 
        try { 
            Thread.sleep(2000);             //assuming service one does some business logic here...
        } catch (InterruptedException e1) { 
            e1.printStackTrace(); 
        } 
        System.out.println("Service Two has finished its work.. waiting for others..."); 
        try { 
            System.out.println("ServiceTwo is now going to wait at the barrier....");
            cyclicBarrier.await();                  //Let's wait for the other threads at the cyclic barrier.
            System.out.println("ServiceTwo woken up at the barrier....");
        } catch (InterruptedException e) { 
            System.out.println("Service one interrupted!"); 
            e.printStackTrace(); 
        } catch (BrokenBarrierException e) { 
            System.out.println("Service one interrupted!"); 
            e.printStackTrace(); 
        } 
        System.out.println("The wait is over, lets complete Service One!"); 
    } 
} 

My question is, when I run this code with CyclicBarrier at two levels, it always ends up into a deadlock it seems. Whereas, when I run the code with CyclicBarrier at level 1 or three, ie new CyclicBarrier(1) or new CyclicBarrier(3), it always completes successfully. What is the issue with level two then?

CyclicBarrier is cyclic, which means it can be reused. When the barrier is initialized with argument 2 , after tripped by serviceOneThread and serviceTwoThread , a new generation starts. The main thread can not trip it alone.

Maybe you need a CountDownLatch .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM