2011-07-12 42 views
2

Java存储器模型提供了DRF保证(数据竞争自由),这意味着在宽松的java内存模型下执行时,数据竞争自由程序会产生与顺序一致执行相同的行为。我有以下问题: a)给定一个活泼的程序,编译器(非常具体的任何jvm实现)做延迟集分析/线程转义分析等,以找出需要插入的围栏指令,使其竞争-自由?或者根据它在哪里执行而做JIT? b)如果编译器做了它(在这种情况下是jvm),为什么我们不能编写racy程序,因为编译器无论如何都会将它转换为无竞争的程序?如果编译器有办法做到这一点(通过围栏插入使它无竞争状态),那么如何编写racy程序(故意),就像java中的一些并发数据结构的实现? c)第三种可能性是jvm本身不会将racy转换为无竞赛节目,但存在其他分析可以为我们做到这一点。是这样吗?通过JVM/JIT插入栅栏指令

回答

3

给定一个racy程序,编译器(非常具体的任何jvm实现)做延迟集分析/线程转义分析等,以找出需要插入的围栏指令,使其无竞争?或者根据它在哪里执行而做JIT?

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

如果编译器这样做(在这种情况下是jvm)为什么我们不能编写racy程序,因为编译器无论如何都会将它转换为无竞争的程序?如果编译器有办法做到这一点(通过围栏插入使它无竞争状态),那么如何编写racy程序(故意),就像java中的一些并发数据结构的实现?

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

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

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

或者第三种可能性是jvm本身不会将racy转换为免竞争程序,但存在可以为我们做的其他分析。是这样吗?

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

如果存在重复我自己,JVM和编译器都不会将“活泼”的程序转换为无竞争的程序,反之亦然。任何相反的行为都是Java内存模型或JVM中的错误。您将需要通过理解程序顺序,同步顺序和发生顺序来编写程序作为无竞争的程序,并且编译器和JVM将确保在运行时确保它。

我想鼓励您阅读this article at InfoQ,以获取有关JVM如何发出内存隔离指令并确保Java内存模型所做承诺的更多详细信息。