- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
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/
我有一个栅栏的 3D 模型。该模型包含 1 个起始柱和 1 个末端柱,中间有一个连接玻璃板。假设我希望能够指定任意长度的栅栏,并将其放置在虚拟世界中。如果可能的话,我将如何处理原始 3D 模型以将其更
x86指令lfence/sfence/mfence用于实现Linux内核中的rmb()/wmb()/mb()机制。很容易理解,这些用于序列化内存访问。但是,在遇到运行时行为中的错误之前,在编写代码时确
以下代码实现了一些无锁(且无原子!)的线程间通信,这些通信需要使用存储和加载内存屏障,但是C++ 11 release-acquire语义不适当,也不保证正确性。实际上,该算法暴露了对发布获取语义的某
我是一名优秀的程序员,十分优秀!