【问题标题】:"gap" between method call and the synchronized block -- avoiding deadlock in concurrency方法调用和同步块之间的“间隙”——避免并发死锁
【发布时间】:2015-04-05 20:46:01
【问题描述】:

下面的方法是SomeType 类的方法——它作为参数的类型。 行 cmets 表示行 #s。

synchronized void someMethod(SomeType other) {  // line 1
                                // line 2
    synchronized (other) {      // line 3
        //...do stuff           // line 4
    }
}

表示为“第 4 行”的块调用了 this 的其他一些同步方法 和other,此代码旨在避免死锁。

但是——假设a.someMethod(b)b.someMethod(a) 被同时调用,其中ab 是不同的实例。

进一步假设b.someMethod(a)a.someMethod(b) 之后被调用,并且它们都被阻止 在第 2 行——ab 中的每一个都获得了自己的锁并等待对方的锁继续进行。

这可以/不会发生吗?

如果是这样 - 在哪些 jdk 实现上?这看起来取决于具体的实现,除非它 明确在 jdk 规范中。

TIA

【问题讨论】:

  • 但是b可以进入someMethod() before a进入第3行的block,每个线程都持有顶级monitor,死锁了。
  • 在我看来确实是个僵局。我见过的常用方法是始终以明确定义的顺序获取互斥锁。
  • @chrylis 当然,我的错。

标签: java multithreading concurrency deadlock synchronized


【解决方案1】:

是的,您描述的死锁可能会发生。它发生的频率可能取决于线程代码的细节;这些天来,您最有可能使用操作系统的本机线程,因此它将更多地依赖于本机操作系统而不是 JDK/JRE。不过,在大多数平台上都可能出现死锁,因此您应该在代码中防范它。

如果您认为该方法的争用会很低,或者您不关心性能,您可以在静态成员或类本身上进行同步,而不是在对象上进行同步。如果您确实关心性能并认为争用会很严重,那么您将需要找出一种方法来确保监视器以相同的顺序锁定,而与调用方法的对象以及方法参数无关。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2021-11-09
    • 2017-01-05
    • 1970-01-01
    • 1970-01-01
    • 2015-07-25
    • 1970-01-01
    • 2021-02-08
    • 1970-01-01
    相关资源
    最近更新 更多