【问题标题】:Java Synchronization with multiple objects/locks与多个对象/锁的 Java 同步
【发布时间】:2014-03-11 10:28:36
【问题描述】:

我想知道是否有包或模型可以帮助我解决这种情况。

假设我有 3 个线程和一堆对象 A、B、C、D、E、F

  • T1 需要锁 A、B
  • T2 需要锁 B、C、D
  • T3 需要 E、F 锁

在这种情况下,如果 T1 和 T3 同时运行就可以了。此外,T2 和 T3 可以同时运行。但是 T1 和 T2 绝不应该同时运行。

另外,请注意

  • 线程可以获得任意数量的锁,而不仅仅是 2 个。(我看到了一个用固定数量的锁解决这个问题的优雅解决方案,但不确定我是否可以在这里应用它。)
  • 显然,我希望每个线程同时获取所有需要的锁以防止死锁。

如果有人可以向我指出支持此用例的软件包,或一些解决此问题的代码 sn-p,请告诉我。

非常感谢。

【问题讨论】:

  • 您确定不能将其简化为需要更少的并发锁吗?
  • 这听起来非常复杂且容易出错,但请看java.util.concurrent.locks
  • 我认为您可以通过确保始终在 A 或 C+D 之前获取 B 并始终在释放 B 之前释放 C+D 或 A 来避免死锁。
  • 您提出的方案不可能导致死锁。没有周期。
  • 不幸的是,情况就是这样。锁定对象是系统中数千个“事物”的 ID。线程将同时处理这些事物的组,并且无法保证哪些事物或多少会被处理

标签: java multithreading concurrency synchronization locks


【解决方案1】:

第 1 步

为您的资源提供自然排序。例如,如果您的资源是字母,则 A 将位于 B 之前,B 将位于 C 之前,依此类推。

第 2 步

只允许你的线程按顺序获取资源。

现在您的线程在任何情况下都不可能陷入死锁。

示例

  • 线程 1 需要锁定资源 ABDE
  • 线程 2 需要锁定资源 BE

我们的线程必须争取锁定资源BD。因为我们强制执行了自然顺序,所以首先获得B 上的锁的线程可以保证获得D 上的锁并顺利进行。失败的线程将等待B 被释放。

【讨论】:

  • 我认为这就是您和阿巴比斯在 cmets 中提到的答案。让我再考虑一下,确保我可以按顺序获取资源。一旦我进一步调查,我会回来接受这个答案
  • 排序不必存在。如果你把随机的东西放入一个数组中,那就变成了你的顺序。你只需要执行你的命令。当每个线程去获取锁时,使其顺序获取它们。如果他们到达一个被锁定的地方,他们会自动睡觉。如果他们不这样做,你就没有使用正确的锁。
  • 如果 2 个对象在排序方面“相等”怎么办?例如。有相同的哈希码?
  • @SashaSalauyou 如果两个对象相等,那么它们最好是同一个对象。对象不能与自身发生死锁。如果这两个对象不相同,那么你的自然排序就有缺陷,你需要提供一个更好的。
【解决方案2】:

为避免在这些情况下出现死锁,您必须对锁进行排序,并在您的应用程序中始终按照所诱导的顺序获取它们。

我知道已经提到了这个答案,并且在您的情况下可能就足够了,但是只有在对象具有可比性时才能进行自然排序:(

对对象进行排序的最佳方法是使用返回哈希码值的 System.identityHashCode(A/B/C...lock object)。但同样不要觉得 100% 安全,因为您可能会成为哈希冲突的受害者,即使机会很少,但您可能会遇到死锁。在这些情况下,您需要在代码中增加安全性。你让你的线程竞争一些单独的“打破平局”锁。希望这些信息有助于更清楚地了解您的问题。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2013-04-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-04-02
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多