gpt4 book ai didi

java - JVM/JIT 的栅栏指令插入

转载 作者:行者123 更新时间:2023-12-04 14:42:17 24 4
gpt4 key购买 nike

Java 内存模型提供 DRF 保证(数据竞争自由),这意味着在宽松的 Java 内存模型下执行无数据竞争的程序将提供与顺序一致执行相同的行为。我有以下问题:a)给定一个活跃的程序,编译器(非常具体的任何jvm实现)是否进行延迟集分析/线程逃逸分析等以找出需要插入的栅栏指令以使其无竞争?还是 JIT 是根据它在哪里执行的?

b) 如果编译器做到了(在本例中为 jvm),为什么我们不能只编写有竞争性的程序,因为编译器无论如何都会将其转换为无竞争性程序?如果编译器有任何办法做到这一点(通过栅栏插入使其无竞争),怎么能(有意地)编写活泼的程序,比如 java 中并发数据结构的某些实现?

c) 或者第三种可能性,即 jvm 本身不会将 racy 转换为 race-free 程序,但存在其他分析可以为我们做到这一点。是这样吗?

最佳答案

Given a racy program, does compiler (to be very specific any jvm implementation) do the delay set analysis/thread escape analysis etc to find out the fence instructions that need to be inserted to make it race-free? or doest JIT do it based on where is it getting executed?

内存栅栏指令特定于架构的指令集。它们不是 JVM 指令集中的等效指令。因此,实际上是 JVM/JIT 向处理器发出了栅栏指令。

If compiler does it (jvm in this case) why cant we just write racy program because compiler is anyway going to convert it into race-free program? And if compiler is any way going to do it (make it race-free by fence insertion), how can one write racy programs(intentionally), like some implementations of concurrent data structures in java?

编译器只会确保在生成字节代码时,对 JVM 中的变量执行的所有操作都遵守 Java 内存模型中指定的规则。具体来说,在优化领域,编译器可以自由优化任何指令集,只要它不影响 Action 之间必须存在的发生前关系或 Action 之间的同步顺序。例如,编译器不会重新组织对 volatile 变量的读写。它还将确保在进入或离开 protected (同步)代码区域时不会违反先行发生关系。

因此,编译器会将“有竞争性”的程序转换为无竞争性程序的说法是不正确的。事实上,假定为无竞争(但不是在 Java 内存模型下)的程序在优化后可能会变成“竞争”程序。

Java 中数据结构的并发实现依赖于 Java 内存模型提供的保证。具体来说,这是从 Java 5 修订后的 Java 内存模型,其中准确指定了 volatile 变量的读写之间的发生前关系。 java.util.concurrent 包中的 ConcurrentXXX 类在很大程度上依赖于 volatile 读取的 promise 行为来确保无竞争行为。在 Java 内存模型下,对 volatile 变量的写入保证在读取之前发生,如果这是程序顺序的话;简而言之, volatile 读取将始终检索变量中数据的最准确版本。并发类利用它来确保数据结构可以由单个线程更新,同时由多个其他线程读取(在任何其他情况下,都会存在竞争条件)。

Or third possibility that jvm itself does not convert racy to race-free program but there exists other analysis that can do it for us. Is it the case?

JVM 发出内存栅栏指令。它不执行任何“racy”程序到“race-free”程序的转换。如果编译器生成的字节码遵循 Java 内存模型,那么 JVM/JIT 将在必要时发出内存栅栏指令 - 当读取/写入 volatile 变量、获取或释放对象上的监视器等时。

冒着重复我自己的风险,JVM 和编译器都不会将“racy”程序转换为无竞争程序,反之亦然。任何相反的行为都是 Java 内存模型或 JVM 中的错误。您需要通过了解程序顺序、同步顺序和 happens-before 顺序,将程序编写为无竞争程序,编译器和 JVM 将保证在运行时确保它。

我鼓励您阅读 this article at InfoQ ,有关 JVM 如何发出内存栅栏指令并保证 Java 内存模型做出的 promise 的更多详细信息。

关于java - JVM/JIT 的栅栏指令插入,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6668597/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com