Reordering of the Java Memory Model

       In the implementation of the program, in order to provide performance, processor and compiler will often command reordering, but not at liberty to re-order, not how you want to sort on how to sort, it needs to meet the following two conditions:

  1. You can not change the results of the program running in single-threaded environment;
  2. There is not allowed to re-sort the data dependencies

       If you have read LZ Part blog will know, in fact, these two points can be attributed to one thing: can not be deduced by the principle happens-before, JMM allow any sort.

as-if-serial semantics

       as-if-serial semantics means that all operations can be optimized to be reordered, but you must ensure that the results of the implementation of the reordering can not be changed, compiler, runtime, processors must comply with as-if -serial semantics. Note that as-if-serial guaranteed only single-threaded environment, invalid multi-threaded environment. Here we use a simple example to illustrate:

int a = 1 ;      //A
int b = 2 ;      //B
int c = a + b;   //C

       A, B, C three operations the following relation: A, B without data dependencies, data dependencies exist A and C, B and C exist, when performing reordering, A, B can freely sort, but must C located in front of, the order of execution may be a a -> B -> C or B -> a -> C. But no matter what the final result of the execution order is always equal to C 3. as-if-serail semantics of the single-threaded program to protect it, it can guarantee the final result under the premise of reordering of the program is always the same. In fact, for the sections of the code, they happen-before the existence of such a relationship:

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

       2 is a program in sequential order rule 3 is transitive. But not to say that by reordering, B ahead of A may execute it, why would the presence of A happens-beforeB it? Here again affirms A happens-before B instead of A will be executed before B, but A to B visible, but with respect to the results of the implementation of this program A to B does not need to be seen, and after they reordering does not affect the result, so I do not think that this reordering JMM illegal. We need to understand this: Without changing the premise of the results of program execution, improve operational efficiency of the program as possible. Let's look at some interesting code:

public class RecordExample1 {
    public static void main(String[] args){
        int a = 1;
        int b = 2;

        try {
            a = 3;           //A
            b = 1 / 0;       //B
        } catch (Exception e) {

        } finally {
            System.out.println("a = " + a);
        }
    }
}

       Reordering according to the rules, the operation A and operation B is likely to reorder, if the reordering, B will throw an exception (/ by zero), A case statement will not execute, it will be equal to a 3 Why? If you follow as-if-serial principle it changed the outcome of the procedure. In fact, abnormal JVM to do a special treatment, in order to ensure as-if-serial semantics, Java exception handling mechanism for reordering do a special deal: JIT will be inserted in the wrong compensatory catch statement when reordering Code (a = 3), although doing so will cause catch inside the logic becomes complicated, but the principle is JIT optimization: optimization logic of the program running as much as possible, even if the catch block to the cost of the logic becomes complicated.

The impact of multi-threaded reordering

       In single-threaded environment due to the as-if-serial semantics, reordering can not affect the final result, but for multi-threaded environment? The following code (volatile classical usage):

public class RecordExample2 {
    int a = 0;
    boolean flag = false;

    /**
     * A线程执行
     */
    public void writer(){
        a = 1;                  // 1
        flag = true;            // 2
    }

    /**
     * B线程执行
     */
    public void read(){
        if(flag){                  // 3
           int i = a + a;          // 4
        }
    }

}

       A thread of execution writer (), thread B executed read (), thread B executed when a = 1 can read it? The answer is not necessarily ( Note: X86CPU does not support the write reordering, if it is operating in x86 above, this would be a = 1, LZ do for a long time did not test it out, and finally check the information found ). Since the operation 1 and the operation control between the present no data dependency between 4 2, it is possible to perform the reordering process, the operation 3 and operation 4 is no data dependency between them can also be reordered, but the operation 3 and operation dependence. If the re-operation between operation 1 and 2 Sort:

       In this execution sequence thread B reads a value certainly less than the thread A is provided, where a multithreaded semantics has been destroyed reordered. Operation between operation 3 and 4 may be reordered, not here set forth. But there is a relationship between a dependent control them, because 3 4 operation will be performed only set up operations. When the code is present the control dependency, will affect the degree of parallelism in the execution sequence of instructions, the compiler and the processor will be used to overcome the effects of control speculation performed dependence on the degree of parallelism. 3 and 4 operation if reordering operation, the first operation performed 4, the first will temporarily stores the calculation results to the reorder buffer, the operation 3 is only true when the calculation result will be written to the variable i by the above analysis, reordering does not affect the results of a single-threaded environment, but will destroy the multi-threaded execution semantics .

Reference material

  1. Zhou Zhiming: "in-depth understanding of the Java Virtual Machine"
  2. Fang Tengfei: "Java concurrent programming art"
Published 67 original articles · won praise 64 · views 10000 +

Guess you like

Origin blog.csdn.net/jack1liu/article/details/103061454