首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >通过JVM/JIT实现栅栏指令插入

通过JVM/JIT实现栅栏指令插入
EN

Stack Overflow用户
提问于 2011-07-13 01:42:22
回答 1查看 755关注 0票数 3

Java内存模型提供了DRF保证(数据竞争自由),这意味着当一个无数据竞争的程序在java的宽松内存模型下执行时,将会给出与顺序一致执行相同的行为。我有以下问题: a)给定一个racy程序,编译器(具体地说,任何jvm实现)是否会进行延迟设置分析/线程转义分析等,以找出需要插入哪些围栏指令才能使其无竞争?或者JIT是基于它在哪里执行的吗?

b)如果编译器这样做了(在这种情况下是jvm),为什么我们不能只写racy程序,因为编译器无论如何都会把它转换成无竞争的程序?如果编译器打算这样做(通过栅栏插入使其无竞争),那么如何(有意地)编写快速程序,就像java中并发数据结构的一些实现一样?

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

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2011-07-13 02:08:39

给定一个活泼的程序,编译器(更具体地说,是任何

实现)是否会进行延迟集分析/线程转义分析等,以找出需要插入哪些围栏指令才能使其无争用?或者JIT是基于它在哪里执行的吗?

存储器隔离指令是特定于体系结构的指令集的。它们在JVM的指令集中没有等价的指令。因此,实际上是JVM/JIT向处理器发出了隔离指令。

如果编译器这样做了(本例中是jvm),为什么我们不能只写racy程序,因为编译器无论如何都会把它转换成无竞争程序呢?如果编译器打算这样做(通过栅栏插入使其无竞争),那么如何(有意地)编写快速程序,就像java中并发数据结构的一些实现一样?

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

因此,编译器将把"racy“程序转换为无竞争程序的说法是不正确的。实际上,一个假定为无竞争(但不是在Java内存模型下)的程序在优化后可能会变得“活跃”。

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

或第三种可能性,即jvm本身不会将racy转换为无种族程序,但有其他分析可以为我们做到这一点。是这样吗?

JVM发出内存围栏指令。它不会将"racy“程序转换为"race-free”程序。如果编译器生成的字节码遵循Java内存模型,那么JVM/JIT将在必要时发出内存隔离指令--读/写易失性变量、获取或释放对象上的监视器等。

冒着重复我的风险,JVM和编译器都不会将"racy“程序转换为无竞争程序,反之亦然。任何相反的行为都是Java内存模型或JVM中的错误。您需要通过理解程序顺序、同步顺序和发生之前顺序来编写无竞争的程序,并且编译器和JVM将保证在运行时确保这一点。

我鼓励您阅读this article at InfoQ,以获得有关Java内存模型如何发出内存围栏指令和保证承诺的更多详细信息。

票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/6668597

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档