Java memory model gives DRF guarantee(Data race freedom) which means that a data race free program when executed under relaxed memory model of java will give same behaviour as of sequentially consistent execution. I have the following question: a) 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?
b) 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?
c) 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?
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?
Memory fence instructions are specific to the instruction set of an architecture. They are no equivalent instructions in the JVM's instruction set. Therefore, it is the JVM/JIT that actually issues the fence instructions to the processor.
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?
The compiler will only ensure that when it generates byte code, all actions performed on variables in a JVM obey the rules specified in the Java memory model. Specifically, in the area of optimization, the compiler is free to optimize any set of instructions as long as it does not affect the happens-before relationships that must exists between actions, or the synchronization order amongst actions. For instance, the compiler will not reorganize reads and writes on volatile variables. It will also ensure that happens-before relationships are not violated when entering or leaving guarded (synchronized) regions of code.
So the statement that the compiler will convert a "racy" program into a race-free one is incorrect. In fact, a program assumed to race-free (but not under the Java memory model) may become a "racy" one after optimizations.
The concurrent implementations of data-structures in Java, rely on the guarantees provided by the Java memory model. Specifically, this is the revised Java memory model from Java 5, where the happen-before relationships between reads and writes of volatile variables, was specified accurately. The ConcurrentXXX classes in the java.util.concurrent
package, relies heavily on this promised behavior of volatile reads to ensure race-free behavior. Under the Java memory model, a write to a volatile variable is guaranteed to happen before a read, if that is the program order; in simpler words, the volatile read will always retrieve the most accurate version of data in the variable. The concurrent classes utilize this to ensure that the data structures can be updated by a single thread, while being read by multiple other threads (in any other scenario, there would be race conditions).
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?
The JVM issues the memory fence instructions. It does not perform any conversion of "racy" programs to "race-free" ones. If the compiler generated bytecode that obeys the Java memory model, then the JVM/JIT will issue memory fence instructions when necessary - when reading/writing volatile variables, acquiring or releasing the monitors on objects etc.
At the risk of repeating myself, neither the JVM nor the compiler will convert a "racy" program into a race-free one, or vice versa. Any behavior to the contrary is a bug in either the Java memory model, or in the JVM. You will need to write the program as a race-free one, by understanding the program order, the synchronization order and the happens-before order, and the compiler and the JVM will guarantee that it will be ensured at runtime.
I would encourage you to read this article at InfoQ, for further details on how the JVM issues memory fence instructions and guarantees the promises made by the Java memory model.
精彩评论