【问题标题】:Deadlock with CyclicBarrier?CyclicBarrier 死锁?
【发布时间】:2017-12-27 06:39:48
【问题描述】:

我对 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!"); 
    } 
} 

我的问题是,当我在两个级别上使用 CyclicBarrier 运行此代码时,它似乎总是会陷入死锁。然而,当我在 1 级或 3 级使用 CyclicBarrier 运行代码时,即 new CyclicBarrier(1) 或 new CyclicBarrier(3),它总是成功完成。那么二级有什么问题呢?

【问题讨论】:

  • 请提供一个最小的例子。您的代码中充满了不相关的信息
  • 您有 3 个参与方,但您将 CyclicBarrier 设置为依赖于 2 个参与方。当前 2 方等待时,屏障将跳闸,而这 2 方将继续执行。屏障现在重置为等待 2 个新方。因此,到达的第 3 方将停留在等待位置并等待第 4 个呼叫等待。

标签: java cyclicbarrier


【解决方案1】:

CyclicBarrier 是循环的,这意味着它可以重复使用。当屏障用argument 2 初始化时,在被serviceOneThreadserviceTwoThread 触发后,新的一代开始。主线程不能单独跳闸。

也许您需要CountDownLatch

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2014-06-08
    • 2013-11-30
    • 2013-12-25
    • 2015-01-29
    • 2017-03-02
    • 2023-03-14
    • 1970-01-01
    相关资源
    最近更新 更多