In addition to Weibo, there is also WeChat
Please pay attention
WeChat public account
Shulou
2025-03-31 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Development >
Share
Shulou(Shulou.com)06/03 Report--
This article mainly introduces the example analysis of happens-before and as-if-serial semantics, which is very detailed and has certain reference value. Friends who are interested must finish it!
Reordering of instruction sequences
When we write code, we usually write it from top to bottom, so the order in which we want to execute is theoretically gradual serial execution, but in order to improve performance, compilers and processors often reorder instructions.
1) compiler-optimized reordering. The compiler can rearrange the execution order of statements without changing the semantics of single-threaded programs.
2) instruction-level parallel reordering. Modern processors use instruction-level parallel technology to execute multiple instructions overlapped. If there is no data dependency, the processor can change the execution order of the statements corresponding to the machine instructions.
3) reordering of memory systems. Because the processor uses caching and read / write buffers, it appears that load and storage operations may be performed out of order.
From the Java source code to the final sequence of instructions actually executed, there are three kinds of reordering:
Happens-before semantics
Starting with JDK 5, Java uses a new memory model and uses the concept of happens-before to illustrate memory visibility between operations. So what on earth is happens-before?
In JMM, if the result of one operation needs to be visible to another, then there must be a happens-before relationship between the two operations, and the two operations mentioned here can be either within one thread or between different threads.
The happens-before rules are as follows:
Program order rules: for each operation in a single thread, the previous operation happens-before any subsequent operation in that thread.
Monitor lock rule: unlock a lock, which is subsequently locked by happens-before.
Volatile variable rule: write to a volatile domain, happens-before any subsequent reads to that volatile domain.
Transitivity: if A happens-before B and B happens-before C, then A happens-before C.
Note:
The fact that there is a happens-before relationship between two operations does not mean that the previous operation must be performed before the latter operation. Happens-before only requires the previous operation (the result of execution) to be visible to the latter operation, and the former operation comes before the second operation in order.
The relationship between happens-before and JMM is shown in the figure:
As shown in the figure, a happens-before rule corresponds to one or more compiler and processor reordering rules.
Reorder
Reordering refers to a means by which compilers and processors reorder instruction sequences in order to optimize program performance.
If two operations access the same variable and one of the two operations is a write operation, there is a data dependency between the two operations. There are three types of data dependencies:
In the above case, as long as you reorder the execution order of the two operations, the execution result of the program will be changed. The compiler and processor may reorder operations, but when reordering, the compiler and processor will comply with data dependencies, and the compiler and processor will not change the execution order of the two operations that have data dependencies.
Note:
The data dependencies mentioned here are only for instruction sequences executed in a single processor and operations performed in a single thread, and data dependencies between different processors and threads are not considered by compilers and processors.
As-if-serial semantics
As-if-serial semantics means that no matter how much you reorder, the execution result of a single-threaded program cannot be changed. Compilers, runtime, and processors must all follow as-if-serial semantics. So compilers and processors do not reorder operations that have data dependencies because such reordering changes the execution result. However, if there are no data dependencies between operations, they may be reordered by the compiler and processor.
The following is illustrated by an example in the book (calculating the area of a circle):
Double pi = 3.14; / / Adouble r = 1.0; / / Bdouble area = pi * r * r; / / C
The data dependencies of the above three operations are shown in the figure:
There is a data dependency between An and C, and there is also a data dependency between B and C. Therefore, in the final sequence of executed instructions, C cannot be reordered before An and B (because C comes before An and B, the result of the program will be changed). However, there is no data dependency between An and B, and the compiler and processor can reorder the execution order between An and B.
Two possible execution orders for the program:
As-if-serial semantics protects single-threaded programs, and compilers, runtime, and processors that abide by as-if-serial semantics work together to create an illusion for programmers who write single-threaded programs: single-threaded programs are executed in program order.
Program order rule
According to happens-before 's program order rules, the above sample code for calculating the area of a circle has three happens-before relationships.
1) A happens-before B.
2) B happens-before C.
3) A happens-before C.
The third happens-before relation here is derived from the transitivity of happens-before.
Note:
Here A happens-before B, but in practice, B can be executed before A, and JMM does not require that A be executed before B. JMM only requires the previous operation (the result of execution) to be visible to the latter operation, and the previous operation comes before the second operation in order. Here, the execution result of operation A does not need to be visible to operation B, and the execution result after reordering operation An and operation B is consistent with that of operation An and operation B in happens-before order. In this case, JMM will think that this reordering is not illegal, and JMM allows such reordering.
The effect of reordering on multithreading
Does reordering change the execution result of multithreaded programs? Or borrow an example from the book:
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}
The flag variable is a tag that identifies whether the variable a has been written. Let's assume that there are two threads, An and B, that first execute the writer () method, and then thread B then executes the reader () method. When thread B executes operation 4, can you see thread A writing to the shared variable an in operation 1?
The answer is: not necessarily.
Since there is no data dependency between operation 1 and operation 2, the compiler and processor can reorder the two operations; similarly, operation 3 and operation 4 have no data dependency, and the compiler and processor can reorder the two operations.
What effect might occur when Action 1 and Action 2 are reordered? (the dummy arrow line identifies the wrong read operation, and the solid arrow line identifies the correct read operation.)
As shown in the figure, operations 1 and 2 are reordered. When the program is executed, thread A first writes the tag variable flag, and then thread B reads the variable. Because the condition is determined to be true, thread B will read the variable a. At this point, the variable a has not yet been written by thread A, where the semantics of multithreaded programs are broken by reordering!
What happens when operations 3 and 4 are reordered. The following is the sequence diagram of the execution of the program after operation 3 and operation 4 are reordered:
In the program, there is a control dependency between operation 3 and operation 4. When there is a control dependency in the code, it will affect the parallelism of instruction sequence execution. To this end, compilers and processors will use guess execution to overcome the effect of control correlation on parallelism. Taking the conjecture execution of the processor as an example, the processor of thread B can read ahead of time and compute astata, and then temporarily save the result to a hardware cache called reorder buffer. When the condition of operation 3 is judged to be true, the calculation result is written into the variable I. Guessing execution essentially reorders operations 3 and 4, where reordering destroys the semantics of multithreaded programs!
Note:
In a single-threaded program, reordering operations that have control dependencies does not change the execution result.
In multithreaded programs, reordering operations that have control dependencies may change the execution results of the program.
The above is all the content of the article "sample Analysis of happens-before and as-if-serial semantics". Thank you for reading! Hope to share the content to help you, more related knowledge, welcome to follow the industry information channel!
Welcome to subscribe "Shulou Technology Information " to get latest news, interesting things and hot topics in the IT industry, and controls the hottest and latest Internet news, technology news and IT industry trends.
Views: 0
*The comments in the above article only represent the author's personal views and do not represent the views and positions of this website. If you have more insights, please feel free to contribute and share.
Continue with the installation of the previous hadoop.First, install zookooper1. Decompress zookoope
"Every 5-10 years, there's a rare product, a really special, very unusual product that's the most un
© 2024 shulou.com SLNews company. All rights reserved.