【问题标题】:multiple thread writing to the same boolean多个线程写入同一个布尔值
【发布时间】:2013-06-05 06:27:50
【问题描述】:

我正在研究图形(节点和顶点)分区算法。

我使用多个线程来尝试识别图中的某些区域。

一旦一个节点被识别为一个区域的一部分,我就为该节点对象设置一个boolean marked 为真。

多个线程可以尝试同时标记同一个节点。

目前我使用同步来确保不会发生任何不好的事情。

但是,自从我从未读取标记的值,直到所有线程都完成处理后。我可以摆脱同步代码吗?换句话说,当同时写入一个布尔变量时会出现什么问题吗?

【问题讨论】:

  • 在设置为 true 时是否标记为 false?
  • 不。只需设置为 true

标签: java concurrency


【解决方案1】:

同时写入布尔变量时会出现什么问题吗?

是的,不是的。当然,结果值不会以某种方式损坏,但是对于在字段上设置哪些更新以及其他线程何时看到这些更新(如果有的话),它将是不确定的。

如果您有多个线程使用此布尔值做出决策,则必须在某些时候提供内存同步。使字段volatile 的成本非常低,除非您有证据表明这是一个性能问题,否则不将字段设置为volatile 很可能是过早的优化。如果您正在比较和设置,那么建议使用 AtomicBoolean,它包装了 volatile boolean 并提供更高级别的方法,例如 compareAndSet(...)

【讨论】:

    【解决方案2】:

    理论上不会,但我不介意声明变量volatile。 Volatile 关键字确保原子访问。

    (前提是写入的顺序无关紧要,所有读取都发生在所有写入之后。)

    【讨论】:

    • 这与boolean 总是发生的原子访问无关,除非您正在执行volatile 无法拯救您的测试和设置操作。这与操作顺序和内存可见性有关。
    • 除非有适当的同步,读线程可能会读到“假”,尽管写线程将布尔值设置为“真”。 OP 描述的内容存在可见性问题。
    【解决方案3】:

    不,当多个线程写入相同的布尔值时,不会出错,但是稍后在不同的线程中读取该值(甚至是很长时间)可能会出现问题。您至少应该将变量标记为volatile 以防止出现问题。

    【讨论】:

      【解决方案4】:

      正如其他人所说,如果您只是尝试从多个线程将其设置为相同的值,则布尔值没有损坏或不正确值的风险。

      但是,您甚至可能不需要它

      直到所有线程完成处理后,我才读取标记的值。

      您显然需要某种障碍来同步协调线程与工作线程(例如Thread.join()CountdownLatch 或您的原始du jour),并且几乎所有这些已经提供了发生之前的关系,这将使您的所有标记对协调线程可见。

      拥有单点同步也恰好比读取大量 volatile 更便宜(我不会称之为过早优化,只是省略了对 volatile 的需求)

      【讨论】:

      • 谢谢.. 这是有道理的。 (我正在使用 thread.join() )以及使用 volatile 布尔值。我将使用布尔值而不是 volatile 布尔值
      【解决方案5】:

      没有。如果写入该变量的顺序无关紧要。

      【讨论】:

      • 问题是读取器线程可能永远无法观察到写入。
      • @assylias 即使“直到所有线程都完成处理后我才读取标记的值”?你能解释一下吗?
      • 写入线程已经完成其工作的事实并不意味着所做的更改已正确发布并且可以从另一个线程读取。
      • 有趣。是因为“发布”更改需要有限的时间,而且我们没有明确标记“发布”操作的边界吗?由于更改是原子的,阅读器线程可能会在更改完成发布之前读取,因此有可能永远不会被读取?
      • 如果没有适当的同步,它们可能永远不会被发布。理论上,如果 JVM 确定一个线程在没有同步的情况下设置了一个变量并且以后从不读取该变量,则在遵守 Java 内存模型的同时,将允许将该写入视为无操作。在这种情况下,更改将永远不会发布......实际上这不太可能发生,并且许多“事物”确实会同步代码。例如,从读取线程调用writingThread.join() 就足以使写入可见。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-12-25
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多