Welcome to search “little monkey technical notes” to follow my public account, you can timely communicate with me if you have any questions.

We write programs in the order in which we write code, does the computer execute in the order in which we write code? The answer is: not necessarily. If there is no dependency between two pieces of code, the compiler and processor will often reorder our coded instructions. Reordering is a means by which the compiler and processor reorder the sequence of instructions in order to optimize the performance of the program. We wrote a Java code from the source code to the last execution order as follows:Source code: the code we write using development tools.

Compiler optimization reordering: The compiler can rearrange the execution order of statements without changing the semantics of a single-threaded program.

Instruction-level parallel reordering: Modern processors use instruction-level parallelism to overlap multiple instructions. If there are no dependencies on the data, the processor can change the execution order of the machine instructions corresponding to the statement.

Memory system reordering: Modern processors use write buffers to temporarily hold data written to memory, which makes it appear that load and store operations may be performed out of order. Let’s look at this example:

Suppose you have two processors, processor A and processor B, and the initialization states of A and B are 0. Execute the following code (all pseudo-code) in processor A:

a=1;
x=b;
Copy the code

Execute the following code in processor B:


b=2;
y=a;
Copy the code

The result that the processor allows to execute is x=y=0. Take a look at the processor/memory interaction diagram:Because modern processors use write caches, they now allow reordering of write-read operations.

What a write buffer does: Because processor and memory are not of the same order of magnitude, each processor has a write buffer that is visible only to its own processor to avoid delays caused by processors pausing to write data to memory. Modern processors flush write buffers in batches and combine multiple writes to the same memory address in write buffers to reduce calls to the data bus.

After reordering, we need to know that on a single-core processor, if two variables have data dependencies, the compiler and processor will not change the order in which two operations that have data dependencies are executed. So how does reordering affect multithreading? Take a look at this example:

public class ReorderExample { int a = 0; boolean flag = false; Public void writer() {// operation 1 a = 1; // operation 2 flag = true; } public void reader() {if (flag) {4 int I = a * a; System.out.println(i); }}}Copy the code

If thread A executes the “writer()” method first and thread B executes the “reader()” method next, can thread B see thread A writing to the shared variable A when it executes?

The answer is not necessarily yes, because operations 1 and 2 have no data dependencies, so the compiler and processor can reorder them. Given that operations 1 and 2 are reordered, it is possible for thread B to execute with the result I =0.

A judgment is first calculated in operation 3 and operation 4, and there is a control dependency between them. When there is a control dependency in the code, it will affect the parallelism of instruction sequence execution. The thread B processor can read and calculate “A * A” ahead of time, then temporarily save the results to a hardware cache called the Reorder Buffer (ROB). When the condition for operation 3 is judged to be true, the result is written to variable I.It can be seen that if there are multiple threads, reordering will affect the results of multithreading