【问题标题】:Does creating a new Thread have a side effect of flushing the cache?创建一个新线程是否有刷新缓存的副作用?
【发布时间】:2011-12-14 19:42:21
【问题描述】:

我想知道在 Java 中创建新线程是否会触发缓存刷新。假设我按以下顺序做这样的事情:

  1. 线程运行并设置变量 X。
  2. 线程创建一个新线程。
  3. 新线程访问 X。

我的问题是:新线程,无论是在它创建时还是在它开始执行时,是否保证看到旧线程在步骤 1 中对 X 所做的更新?我了解如果旧线程将来更改 X 的值,不保证新线程会看到这些更改。没关系。我只想知道新线程是否会在不需要显式同步的情况下启动时看到正确的值。

当我第一次决定研究这个主题时,我认为一个简单的谷歌搜索会立即找到答案,但由于某种原因,我找不到任何解决这个问题的结果。

【问题讨论】:

  • 如果您可以只创建有问题的变量volatile,为什么还要依赖这些模糊的保证(如果它们存在的话)?
  • @delnan:这里没有什么晦涩难懂的。这种行为在 Java 语言规范中有明确规定。
  • 现在一个更模糊的保证问题可能是:“A 写入 X;B 创建;C 读取 X”——这个行为是否已定义? :-)
  • @pst:不确定 B 是如何相关的。在这种情况下,C 可以保证看到默认值或 A 写入的值,但没有指定是哪一个。 (假设没有其他对 X 的写入,并且“A 写入 X”和“C 读取 X”操作未通过任何其他方式同步,例如通过使用 volatile)。
  • @pst:创建线程和等待(加入)线程时有同步。

标签: java multithreading concurrency thread-safety


【解决方案1】:

是的。

在 java 中,有一个“happens-before”关系,它指定了两个动作之间可见的记忆效果。如果“A 发生在 B 之前”,则操作 B 可以保证看到操作 A 所做的所有更改。

启动线程会在“thread.start()”调用和在新线程上执行的所有代码之间创建“先发生”关系。因此,可以保证新线程在第一个线程上看到更改变量 X 的记忆效应。

有关happens-before 关系的快速概述,请参阅java.util.concurrent 包概述的Memory Visibility 部分。在您的情况下,有趣的部分是:

  • 线程中的每个动作都发生在该线程中的每个动作之前
  • 在线程上启动的调用发生在已启动线程中的任何操作之前。

如果您好奇,请点击更多链接:

【讨论】:

  • 一个很好的答案,但是,通读这个概要让我不清楚这是否被定义:线程存在,A, B, variable X is unknownA writes X; B creates C; C reads X。请注意C 是由B 而不是A 创建的——因此A 和C 没有happens-before? (请注意,这不是原始问题所问的,这个问题确实回答了,只是在沉思!:-)
  • @pst:是的,你是对的。在这种情况下,“A 写入 X”和“C 读取 X”操作之间没有发生之前。
  • @PeterŠtibraný:你的意思是 is 在“B 创建 C”和“C 读取 X”之间发生,但在“A 写入 X”和任何其他之间没有B 或 C 中的操作。
  • 作为参考,我检查了链接文档的特定部分,该部分记录了 Thread.start() 的同步:“同步动作导致动作的同步关系,定义如下: - 动作启动线程的线程与它启动的线程中的第一个动作同步。” [从 17.4.4 开始]
猜你喜欢
  • 2014-03-27
  • 2014-01-27
  • 2016-06-09
  • 2014-04-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-03-13
  • 2020-04-04
相关资源
最近更新 更多