【问题标题】:Deadlock without cycle无循环死锁
【发布时间】:2011-04-01 09:01:41
【问题描述】:

如果我绘制了一个图形来表示对阻塞函数(java 同步方法)的所有可能调用,并且我在这个图形中没有任何循环,我可以确定死锁是不可能的。 petri-nets 不是这样工作的吗?

我不是在寻找这样的答案:使用一些怪物框架等等。

我想用同步方法处理我的多线程。

EDIT1:箭头表示一个类调用另一个类的任何同步方法 EDIT2:klick@这里的例子,显示一个循环

【问题讨论】:

    标签: java synchronization deadlock petri-net


    【解决方案1】:

    不,这还不够。假设您必须线程:A 和 B。A 调用对象 o1 的方法 m1,该方法调用对象 o2 的方法 m1。线程 B 调用对象 o2 的方法 m2,它调用对象 o1 的方法 m2。假设所有方法都是同步的。现在,A 和 B 的并发执行会导致死锁。虽然,方法之间没有循环调用关系。

    这是作业吗?

    即使您对类进行了编辑,这还不够,因为您可以通过非同步方法调用来关闭循环。

    【讨论】:

    • 有趣的是,如果你画的是对象图而不是方法图,那么就有一个循环:o1 -> o2 -> o1。这是否适用于所有不涉及等待/通知的死锁场景?不过,这可能不是一种让你在实践中走得很远的方法。
    • 看看我编辑的图片,它显示了汤姆描述的内容。我只谈论对象级别的连接。我的第一个描述是错误的......
    • @Franz Kafka:看,我回答的最后一句话。
    【解决方案2】:

    没有。考虑:

    private static final Semaphore foo = new Semaphore(1);
    private static final Semaphore bar = new Semaphore(1);
    
    private static void one() throws InterruptedException {
        foo.acquire();
        bar.acquire();
        bar.release();
        foo.release();
    }
    
    private static void two() throws InterruptedException {
        bar.acquire();
        foo.acquire();
        foo.release();
        bar.release();
    }
    

    有关可运行示例,请参阅 http://pastebin.com/QfK5ZByj。对我来说,它很快就会陷入僵局。

    【讨论】:

    • 好吧,这很有趣。如果箭头是线(指向两个方向),那么这将是一个循环。单向箭头不是循环。
    【解决方案3】:

    某些方法可能会在没有 synchronized 关键字的情况下阻塞。例如,这适用于包 java.util.concurrent 中的许多方法。您还应该考虑方法内部的 synchronized 块。

    如果只考虑同步方法,您可能会在方法调用中出现没有循环的死锁,因为同步方法使用对象实例作为监视器。例如,如果您有两个对象 A 和 B,每个对象都有同步方法 1() 和 2()。如果A.1()调用B.1(),B.2()调用A.2(),虽然方法中没有循环,但是如果一个线程同时调用B.2()另一个线程调用A.1()那么就会出现死锁风险。

    【讨论】:

    • 好吧,我想我解释错了。如果一个班级调用另一个班级,我正在谈论绘制一个尖箭头。所以箭头是在类级别而不是方法级别。但如果使用同步类,我只考虑绘制箭头。你懂我的意思吗? :-)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-03-14
    • 2018-03-12
    • 2021-08-21
    • 2021-08-12
    • 1970-01-01
    • 2019-05-29
    相关资源
    最近更新 更多