Can a Java compiler or JVM change the order of independent instructions?

Take the following statements:

int d0, d1; int[] ds = {0, 0}; 

Now one thread has the following instructions:

 d0++; d1++; 

while the other thread has the following statement:

 ds[1] = d1; ds[0] = d0; 

If we run these threads in parallel, it’s obvious that there are three combinations that ds might look like: {0, 0}, {1, 1} and {1, 0}.

Now the big question is: can there be {0, 1}? Can the / JVM compiler just replace the command because it thinks they are not related? If so, what exactly are the β€œrules” for this behavior and does it depend on the compiler or the JVM?

+4
source share
3 answers

Yes, {0, 1} also possible. The Java memory model is not strong enough to guarantee order in this case. This does not even require reordering the commands - this will happen anyway if you run the program only on x86 or x86_64.

To be clear here, the actual CPU hardware will reorder these loads and storage only if it's x86.

See Frequently Asked Questions About the Java Memory Model

+6
source

In the absence of proper synchronization, this is indeed possible.

The Java language specification defines the semantics of multi-threaded Java programs in chapter 17. This chapter is pretty hard to understand, but it contains official rules you can rely on. In particular, he writes :

The memory model describes, given the program and the execution trace of this program, whether the execution trace is a legitimate program execution. The Java programming language memory model works by checking each read in the execution trace and verifying that the record observed by this read is valid according to certain rules.

The memory model describes the possible behavior of the program. An implementation can freely create any code that he likes, if all the programs arising as a result of execution lead to a result that can be predicted by the memory model.

To give an approximate overview, the memory model determines what happened before the relationship; any reordering should be consistent . The usual way of establishing occurs earlier than the actions performed by different threads is to synchronize these actions, for example, with a synchronized block or writing to or reading from a mutable variable.

In the absence of such synchronization, the runtime will execute threads independently of each other, allowing any reordering of the current thread it cannot observe.

That is, if you have a mutable sharing state, you usually need to synchronize the threads by accessing it.

+2
source

Yes, both the compiler and jvm (the "at the exact moment" compiler) can reorder commands. In addition, a hardware processor may work. To prevent unwanted reordering, memory barriers should be used.

0
source

Source: https://habr.com/ru/post/1446755/


All Articles