问题标签 [happens-before]

For questions regarding programming in ECMAScript (JavaScript/JS) and its various dialects/implementations (excluding ActionScript). Note JavaScript is NOT the same as Java! Please include all relevant tags on your question; e.g., [node.js], [jquery], [json], [reactjs], [angular], [ember.js], [vue.js], [typescript], [svelte], etc.

0 投票
2 回答
512 浏览

java - 如果在java中线程A在线程B之前开始,那么A将在B之前被os调度?

我正在阅读《Understanding the JVM Advanced Features and Best practice》,其中有一段代码解释了java中的happens-before规则。我无法理解。代码如下:

假设线程在代码中的线程A之前开始。B我可以理解,我们不知道getValue()线程 B 中返回的结果,因为它不是线程安全的。setValue()但是书上说如果在函数和函数中添加同步关键字getValue(),则不存在线程安全问题,方法getValue()将返回正确的值。书中解释说,因为synchronized符合发生前发生的规则。所以我通过下面的代码有两个问题。

  1. 虽然A.start()run beforeB.start()和 value is volatile,但我们不能确保线程 B 可以打印出来10,对吧?因为线程 B 可能首先被 JVM 调度,所以线程 B 将打印 0 而不是 10。
  2. 即使A线程被 JVM 调度在线程之前B,但我们也不能保证this.value = value之前被 JVM 执行的指令,return this.value因为 JVM 会再次对指令进行排序。我的理解是对的吗?请帮我。
0 投票
2 回答
154 浏览

java - JMM 在实践中

考虑以下用 Java 编写的多线程代码:

共享变量:

线程 1:

线程 2:

假设最初n = v = false

现在:

  • 的输出是否v=false暗示 的输出n=true
  • n如果是 volatile会发生什么变化?
  • n如果是的话会发生什么变化java.util.List(这样n = true就变成n.add("something")了并且输出n=true变成了["something"])?
  • UPD3:如果所有对它vAtomicBoolean读取和写入都使用compareAndSet语义执行会怎样?

你能根据 Java 内存模型论证你的立场吗?

UPD:System.out.println("n=" + n)视为只是阅读n. 对于v.

UPD2:您能否对 JSR-133 sec 中所示的第 1 和第 4 种情况进行一些分析。8?

0 投票
1 回答
602 浏览

java - 是否发生在即 hb(x,y) 与 hb(y,x) 不同之前?

查看答案、评论和jls-17.4.2后可接受的答案

1) 反对称性质成立,如 - user3707125 所指

2) 锁之间的hb关系实际上是解锁和加锁hb(ul, l)之间的关系,与hb(l, ul)不同。
提示 -来自 JSL的 shmosel -

监视器上的解锁发生在该监视器上的每个后续锁定之前。

3) james-large 对 hb 的合理解释


实际问题是:

Java 内存模型(JMM)描述了发生在几个动作之间的关系之前。如果“x”和“y”是两个动作,它们之间有 h(x,y) 关系。JMM 还指出,如果实现(编译器、运行时或硬件)获得与依次执行“x”和“y”相同的结果,则可以自由地重新排序这些执行。

所以我认为,

我对吗?还是我错过了什么?

更新:
对于涉及锁的操作,如何建立 hb 关系。由于不同线程锁定的事件不能由程序顺序定义,因此只是不确定性的,并且取决于指令和调​​度程序等几个因素。
所以在两个锁定动作之间 - l1 和 l2 如何定义关系 hb(l1 , l2) 或 hb(l2, l1)。似乎两者都可以接受。在这种情况下,两者似乎相等。
l1 和 l2 是对同一个对象的锁定操作。 l1 和 l2 不是锁

澄清(基于评论):当不同线程对同一个对象进行锁定时,锁定动作肯定是互斥的。

0 投票
1 回答
280 浏览

java - java并发 - 指令级并行(ILP)是否在底层使用

Java 或一些类似语言中的并发是通过线程或任务级并行实现的。但在后台,硬件或运行时是否也使用 ILP 来实现最佳性能。
进一步详细说明:在具有多个线程(例如每个核心 2 个)(即每个系统总共 8 个线程)的多核处理器(例如每个系统 4 个)中,java 线程在几个(在这种情况下为 8 个)处理器之一中执行线程。但是,如果系统确定所有或几个其他线程除了保持理想之外什么都不做,硬件或运行时是否可以进行任何合法的重新排序并在相同或其他内核上的其他线程中执行它们并将结果取回(或在 main记忆)
我很担心 java 实现是否允许这样做,或者甚至在没有 JVM 甚至不知道任何东西的情况下,它也取决于硬件来独立处理。

0 投票
1 回答
568 浏览

distributed-system - Consul 键值存储是否为我们提供了使用两个不同键对两次写入进行排序的任何保证?

假设我们只有两个节点 A 和 B。

当我们在节点 A 上发出这两个命令时,

PUT one key1 happens-before PUT two key2)然后GET/v1/kv/key2节点B上返回two,是否保证GET/v1/kv/key1节点B上返回one?换句话说,Consul KVS 是否尊重节点 A 上两次写入之间的发生前关系?

Consul 使用共识协议来提供一致性(由 CAP 定义)。

是的,但我的理解是 CAP 定理没有谈论多个寄存器。这两次写入最终可能传播到节点 B,但是否可以保证我们永远不会看到意外的中间状态?

0 投票
1 回答
111 浏览

java - 这种非标准的 Java 同步模式有效吗?

假设我有两个线程像这样运行:

  • 线程 A 在更新共享图像的像素时执行计算
  • 线程 B 定期读取图像并将其复制到屏幕

线程 A 快速执行工作,例如每秒 100 万次更新,所以我怀疑经常在锁/互斥/监视器上锁定和解锁是个坏主意。但是,如果没有锁并且无法建立从线程 A 到线程 B 的先发生关系,那么根据 Java 内存模型(JMM 规范),线程 B 根本不能保证看到 A 对图像的任何更新。

所以我认为最小的解决方案是线程 A 和 B 都在同一个共享锁上定期同步,但在同步块内实际上不执行任何工作 - 这就是使模式非标准和可疑的原因。用半真半伪代码来说明:

这样添加空同步块是否正确实现了线程A向线程B传输数据的效果?还是有其他我无法想象的解决方案?

0 投票
1 回答
866 浏览

java - 多深的易失性出版物保证?

众所周知,如果我们有一些对象引用并且该引用具有最终字段 - 我们将看到来自最终字段的所有可访问字段(至少在构造函数完成时)

示例 1:

据我了解,在这种情况下,我们保证该bar()方法始终输出object,因为:
1. 我列出了类的完整代码,Foo并且映射是最终的;
2. 如果某个线程会看到引用 ofFoo并且这个引用 != null,那么我们可以保证从最终map引用值到达的值是实际的。

我也认为

示例 2:

bar()在这里,我们对方法有相同的保证,但是尽管分配发生在分配之前,我们仍然bar2可以抛出 。NullPointerExceptionnonFinalMapmap

我想知道 volatile 怎么样:

示例 3:

据我了解,bar()方法不能抛出NullPoinerException,但可以打印null;(我完全不确定这方面)

示例 4:

我认为在这里我们对bar()方法有相同的保证也bar2()不能抛出NullPointerException,因为nonVolatileMap赋值写了更高的易失映射赋值,但它可以输出 null


在 Elliott Frisch 评论之后添加

通过比赛示例发布:

请证明或更正我对代码片段的评论。

0 投票
3 回答
208 浏览

java - Happens-before 使用不同的显示器

在这个网站上的某个地方(我不记得这个问题)有人声称,对于不同的监视器和不同的 volatile 变量,发生之前发生的 relashionship,即

如果线程 T1 离开 synchronized(O1){} 块后线程 T2 进入 synchronized(O2){} 块,T2 将看到 T1 所做的所有更改。解释是当线程离开同步块(或写入 volatile 变量)时,它会将其缓存刷新到内存中。当一个线程进入同步块(或读取 volatile 变量)时,它会丢弃它的缓存并从内存中读取。这是真的吗?

0 投票
0 回答
30 浏览

java - 相对于新线程而言,Thread.start() 线程之前的操作是否安全?

Thread.start()与新线程的启动相关的变量可见性和/或指令顺序是否有任何保证?

具体来说,在下面的简约示例中,我是否正确假设var应该是volatile为了使输出具有确定性并始终打印“var = 10”?

注意:我的问题仅适用于 Java 5 中引入的“新”Java 内存模型

0 投票
1 回答
124 浏览

java - Java 多线程没有发生之前的关系

我有两个线程使用相同的线程,并且由于之前发生的关系,我已经阅读了byObject obj所做的每一个更改都将是可见的。objThread AThread B

我想要做的是相反的,objThread A不可见的情况下改变,Thread B但我不知道如何做到这一点。

我尝试创建一个ThreadLocalin Thread B,将其设置在run()方法中,并使用ThreadLocal.get()而不是objinThread B但它一直在读取更改。

有谁知道如何实现这一目标?

提前致谢

编辑:(MVCE)

主线程

线程 B

当我继续运行主线程时会出现问题,因为它的下一步是刷新整个页面,因此email设置为一个新实例,这使我丢失了 MyThreadLocal 的电子邮件信息