In-depth understanding of the Java Memory Model (b) - reordering

Data dependencies

If both access the same variable operation, and both operations of a write operation, then there is data dependency between the two operations. Data dependency min following three types:

name The sample code Explanation
Read after write a = 1;b = a; After writing a variable, read this position.
After Write Write a = 1;a = 2; After writing a variable, write this variable.
Reading writing a = b;b = 1; After reading a variable, write this variable.

The above three cases, as long as the order of execution of two reordering operation, the execution result of the program will be changed.

As mentioned earlier, the compiler and processor may have to do reordering operation. Compiler and a processor at the reorder, will comply with the data dependency, and the compiler does not change the order of execution of the processor data dependency exists two operations.

Note that the data dependencies between operations and the sequence of a single thread of instructions of said data dependency herein is performed only for a single processor executing in a processor and a different thread is not considered different compilers and processors.

as-if-serial semantics

as-if-serial means semantic meaning: no matter how reordering (compiler and processor in order to improve the degree of parallelism), the execution result (single-threaded) program can not be changed. Compiler, runtime and processors must comply with as-if-serial semantics.

In order to comply with as-if-serial semantics, the compiler and the processor does not make the operation of reordering data dependencies, since such reordering can change the result. However, the absence of data dependencies between operations if these operations could be reordered compiler and a processor. To illustrate, consider the following code sample area of ​​a circle is calculated:

double pi  = 3.14;    //A
double r   = 1.0;     //B
double area = pi * r * r; //C

The above three operations data dependency as shown below:

Shown, there is data dependency between the above figure A and C, there is also a data dependency between B and C. Therefore, in the final sequence of instructions executed, C can be reordered in front of the A and B (C moved up the A and B, the results of the program will be changed). But no data dependencies between A and B, the compiler and the processor may perform reordering sequence between the A and B. The figure is two execution order of the program:

as-if-serial semantics of the single-threaded programs to protect up to comply with as-if-serial semantics compiler, runtime and processors together to create an illusion for the programmer to write single-threaded programs: the program is based on single-threaded programs order execution. as-if-serial semantics of the single-threaded programmer need not worry about reordering interfere with them, there is no need to worry about memory visibility problems.

Program sequence rules

The program sequence rules happens- before, there are three happens- before calculating the relationship between the sample code above circle area:

  1. A happens- before B;
  2. B happens- before C;
  3. A happens- before C;

Here happens- before the third relationship is deduced from the transfer of the happens- before.

Where A happens- before B, but actually it can schedule the execution B (see after reordering the order of execution above) before A. Mentioned in the first chapter, if A happens- before B, JMM is not necessarily required to be performed prior to A B. JMM former requires only one operation (executed result) after the operation of a visible and sequenced previous operation before the second operation. A result of operation performed here need not be visible to the operator B; and reordering the execution result of the operation A and Procedure B, consistent with the results of the operation A and operation B executed in order happens- before. In this case, JMM think that this reordering is not illegal (not illegal), JMM allow such reordering.

In the computer, software technology and hardware technology we have a common goal: the program without changing the results of the premise, as far as possible the development of parallelism. Compilers and processors comply with this objective, by definition happens- before we can see, JMM comply with the same goal.

The impact of multi-threaded reordering

Now let's see if reordering will change the results of the implementation of multithreaded programs. Consider the following sample code:

class ReorderExample {
int a = 0;
boolean flag = false;

public void writer() {
    a = 1;                   //1
    flag = true;             //2
}

Public void reader() {
    if (flag) {                //3
        int i =  a * a;        //4
        ……
    }
}
}

flag variable is a tag used to identify whether a variable has been written. It is assumed that there are two threads A and B, A first executes writer () method, then thread B then performs Reader () method. Thread B 4 while performing the operation, the ability to see one pair of shared variables in a thread A write operation?

The answer is: not necessarily see.

Since the operation 1 and operation 2 no data dependencies, the compiler, and the two processors may operate reordering; Similarly, 3 and operation 4 operation no data dependencies, the compiler and the processor may operate the two heavy Sort. Let's take a look at when the operator 1 and 2 reordering operation may produce what effect? Consider the following program execution timing chart:

As shown above, the operation 1 and operation 2 made reordering. When the program is executed, the thread A first write flag variable flag, then thread B reads this variable. Since the condition is true, the thread B reads the variable a. At this point, there is no variable has been written a thread A, where the semantics of a multithreaded program was destroyed reordered!

※ Note: This article is unified with a dotted red line arrow indicates an error of a read operation, a read operation indicates the proper virtual green arrow line.

Here let us look, when the operation 3 and operation 4 reordering will have any effect (this reordering means can be controlled dependent Incidentally). The following is the operation after 3 and 4 reordering operation, a timing chart of a program executed:

In the process, the operation 3 and operation 4 control dependency exists. When the code is present the control dependency, it will affect the degree of parallelism in the execution sequence of instructions. To this end, the processor and compiler using guess (speculation) performs control to overcome the influence of the correlation degree of parallelism. Execution processor to guess an example, the thread B executed in advance and calculate the processor can read a * a, and temporarily stores the calculated result to a called reordering buffer (reorder buffer ROB) hardware cache. Next, the operation when the determination condition 3 is true, put the calculation result is written in the variable i.

We can see from the figure, the operation speculation performed substantially 3 and 4 do reordering. Reordering semantics here destroyed multithreaded programs!

In single-threaded program, the present control operation of reordering dependent execution result does not change (which is as-if-serial semantics allow the operator presence control relies reason do reordered); but a multithreaded program, reordering control operation dependent present, it may change the result of the program execution.

 

Published 136 original articles · won praise 6 · views 1491

Guess you like

Origin blog.csdn.net/weixin_42073629/article/details/104741401