【问题标题】:Let thread A block B & C and vice versa, but not let thread B block thread C and vice versa?让线程A阻塞B和C,反之亦然,但不让线程B阻塞线程C,反之亦然?
【发布时间】:2015-04-10 12:32:26
【问题描述】:

我有一个问题,我有一个数据结构和多个线程试图对其进行操作。说得尽量简单:我有线程A、B和C。线程A只能做它的操作,只要B和C不对数据集做任何改变。不过,B 和 C 可以在大部分时间同时在片场工作。所以目标是:

  • 线程 A 阻塞 B 和 C
  • 线程 B 和 C 块 A
  • 线程 B 不会阻塞 C(反之亦然)

问题是,我怎样才能做到这一点? 我希望很清楚我要做什么。如果没有,请随时发表评论。我故意不提供任何代码,因为我认为这样更容易理解问题(很多长代码)。

【问题讨论】:

  • 你总是会同时拥有 3 个线程,还是有多个线程? @菲尔
  • @TimoH 大多数时候会有超过 3 个线程。例如 1 个线程执行 A 操作,9 个线程执行 B 或 C 操作。这意味着总会有 1 个像 A 一样的线程,只有在没有其他线程在运行时才能运行,但可以有任意数量的其他线程,它们可以并行运行。
  • 我猜你需要另一个类作为信号量来帮助协调线程何时应该处理。

标签: java multithreading concurrency locking


【解决方案1】:

您可以使用ReentrantReadWriteLock

【讨论】:

  • 如果有多个读者而只有一个作者,这对我来说很有意义。然而,在我的情况下,多个线程(示例中的 B 和 C)可以同时写入(只要它们更改的元素不同),但是 A 是读取器,并且只有在 B 没有进行任何更改时才能读取和 C. ReentrantReadWriteLock 是否也适用于该概念?
  • @Phil 您的线程实际上正在执行读/写并不重要。 B,C 将获取读锁(即使他们执行写操作),因为它不是独占的,而 A 将获取写锁,因为这会阻止任何其他访问。
  • @Phil,线程无法知道操作是“读”还是“写”。
  • @Zielu 谢谢,在这种情况下,这将按我的需要工作!
  • @skozlov 除非您在答案中添加更多单词(代码)。它很可能会作为 LinkOnlyAnswer 被删除,即使它是正确的并且为作者工作。
【解决方案2】:

您想为此使用具有 2 个许可的信号量。

您的 A 线程将始终要求两个许可 (acquire(2))。

您的 B 和 C 线程将只请求一个许可 (acquire())。

这样 B 和 C 可以始终一起工作,A 将阻止 B 或 C(因为没有可用的许可)。 B 或 C 将阻止 A,因为只剩下一个许可证。

它适用于任何已知数量的 (B,C) 线程,因为信号量可以设置为此数量。主要问题是如果 B 和 C 总是获得一张许可证,A 可能会挨饿。 因此,如果 N = nr(B)+nr(C),那么任何类型 A 的线程都需要 (N)。它不适用于未知数量的 B、C,因为信号量允许数量不能动态增加。

【讨论】:

  • 我认为如果他只使用 3 个线程,这将是正确的解决方案,但我认为如果他有多个线程来完成 A 和 B + C 的工作,这将行不通
  • 只要所有 A 线程都需要 N 个许可,其中 N = (B+C) 的数量,它就可以工作。如果事先不知道数字,它就不起作用。
  • @Zielou 是的。但如果他动态产生线程,我猜它会变得更加复杂。例如。 N = B + C = 2 ,A 尝试获取 N = 2 的信号量,因此 aquire(2),现在 D 加入环,具有与 B + C 相同的权限,因此 N = 3,但 A 尝试获取N = 2 的信号量。希望很清楚
  • @TimoH 谢谢你们。正如我所想,这也可以。为了学习,我可能也会尝试一下。不过我现在确实使用了 ReentrantReadWriteLock,它工作得很好,非常感谢!
【解决方案3】:

你需要让你的对象线程安全。

简而言之,您必须:

  1. 将您的字段设为私有
  2. 找到您的关键部分并使用synchronized bloc 保护它们

在这个page 中很好地恢复了这个概念并解释了其他方法。

一旦您的字段在基本 CRUD 操作(创建、读取、更新、删除)上得到正确保护,您就可以使用特定方法专门为线程 B 和 C 以及其他线程 A 读取数据

【讨论】:

  • 我不太明白你最后一句后半部分的意思。其余的对我来说很清楚,这不是大问题,谢谢。
猜你喜欢
  • 1970-01-01
  • 2018-02-16
  • 2017-06-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-03-13
  • 1970-01-01
  • 2012-06-16
相关资源
最近更新 更多