Java并发屏障示例死锁

Posted

技术标签:

【中文标题】Java并发屏障示例死锁【英文标题】:Java concurrency barrier example deadlock 【发布时间】:2018-10-11 07:42:17 【问题描述】:

我正在尝试实现自定义Barrier 示例,以了解有关Java 并发的更多信息。我有一个可运行的类:

public class Barrier implements Runnable 

    private static Semaphore barrier = new Semaphore(0);
    private static int toWait = 5;
    private static int counter = 0;

    private static long sleepTime;

    public static int ID = 0;

    private int id = ++ID;

    public Barrier(long sleep)
        sleepTime = sleep;
    

    @Override
    public void run() 

        try 

            Thread.sleep(sleepTime);

            counter++;
            if (counter == toWait)
                barrier.release(counter);
            
            barrier.acquire();

            System.out.println("Thread with sleep: " + id + " proceeds");

         catch (InterruptedException ex) 
            Logger.getLogger(Barrier.class.getName()).log(Level.SEVERE, null, ex);
        

    


然后在main 函数中,我创建5 个线程并启动它们。在运行时,我遇到了僵局,我无法解决。谁能告诉我我做错了什么?

【问题讨论】:

counter 需要是一个原子整数。 sleepTime 不应该是静态的。 【参考方案1】:

查看文档:

获取一个许可证,如果一个可用并立即返回,将可用许可证的数量减少一个。

如果没有可用的许可,则当前线程将被禁用以用于线程调度目的并处于休眠状态,直到发生以下两种情况之一:

其他一些线程为此信号量调用 release() 方法,并且当前线程接下来被分配一个许可;要么 其他一些线程中断当前线程。

因此,由于您对所有线程进行了一次aquire,并且没有一个线程被释放,因此它们都将保持被获取状态。也许将其中的 Counter on 设置为 5。因此,您可以释放最后一个元素并通过执行此操作删除其他元素的获取状态。

编辑:哦,您的信号量有 0 个许可。根据您的情况使用 1 或 2 对其进行初始化。

【讨论】:

【参考方案2】:

没有互斥。为了解决这个问题,我需要添加另一个信号量,并用该信号量的acquire release 包围计数器增量。

【讨论】:

以上是关于Java并发屏障示例死锁的主要内容,如果未能解决你的问题,请参考以下文章

Java并发多线程编程——CyclicBarrier

Java线程与并发编程实践----同步器(Phaser)

Java并发工具类同步屏障CyclicBarrier

java并发之同步辅助类

Java并发工具类之同步屏障CyclicBarrier

Java 并发工具CountDownLatch和CyclicBarrier 原理解析