Visibility, Order and Atomicity and Non-Atomic Agreements

        After introducing the relevant operations and rules of the Java memory model, you will find that it is mainly built around how to deal with the three characteristics of atomicity, visibility and ordering in the concurrent process, which is also the core concept of concurrent programming. .

visibility

        Visibility means that in a concurrent environment, when a thread modifies the value of a shared variable, other threads can immediately know about the modification.

In the architecture of a multi-core processor, due to the existence of the CPU cache, when a core modifies the value of a shared variable, it may not be flushed back to the main memory immediately, and even if it is flushed back to the main memory immediately, others will also use the shared variable. The thread does not necessarily immediately sense the change in its data and reload the shared variable from main memory.

In Java, there are several ways to ensure concurrent visibility (in fact, the bottom layer is achieved by setting memory barriers).

1. The volatile keyword. A volatile-modified variable guarantees that the new value is immediately synchronized to main memory and flushed from main memory immediately before each use.

2. Synchronized and Lock display locks. According to the JMM memory interaction rules: before performing the unlock operation on a variable, the variable must be synchronized back to the main memory. Before performing the lock operation on a variable, the value of the variable in the working memory will be cleared and reloaded from the main memory.

3. The final keyword. Once the field modified by final is initialized in the constructor and the reference to "this" is not passed out during the initialization process, the value of the final field can be seen by other threads.

4. Atomic variables. Atomic variables like AtomicInteger actually use the volatile keyword internally.

5. All other operations follow the happens-before principle. Of course, all the means mentioned above belong to this category.

 

orderliness 

Ordering actually has the following semantics:

1. Problems caused by instruction reordering for operations that are not related to single-threaded internal data.

       As described in the  Java Memory Model JMM 4 volatile keyword  chapter, the reordering of the identification variable after initialization will cause an error in the execution of another thread. This problem can be solved by using the Volatile keyword.

2. The disorder of multi-threaded concurrent execution.

       The out-of-order execution of critical section code by multithreading is the embodiment of this problem. Use the synchronized keyword and the Lock explicit lock to lock the critical section, that is, the multi-threaded serial execution of the critical code.

3. Because the visibility after modifying the shared variable cannot be guaranteed, the program execution result cannot reach the expected disguised ordering problem.

       Generally speaking, this is a series of problems caused by the phenomenon of "working memory or processor cache and main memory synchronization delay". Strictly speaking, item 1 also belongs to this category, but the problem described here is broader. The operation that satisfies the happens-before principle will be the unified judgment standard for this kind of problem. In the case where a clear order cannot be deduced through the principle of happens-before, the synchronized keyword and Lock can be used to solve the problem . All questions.

 

atomicity

Atomicity means that some operation(s) are semantically atomic. That is, an operation or multiple operations are either all executed and the execution process is not interrupted by any factors (including CPU suspension scheduling), or none of them are executed. If an operation is atomic, then in a multi-threaded environment, there will be no strange problems such as variables being modified by other threads during the operation. For example, a read or write operation to a single variable is an atomic operation, because the read or write operation is atomic at the low-level instruction level of the computer, and an instruction operation to a certain memory address can only be exclusively shared by one instruction at a time. Also from the previous chapter I know that CAS operations are also atomic operations.

        In Java, reads and assignments to variables of primitive data types are atomic operations. This seems simple, but it is not so easy to understand. See an example below:

 

x = 10; //statement 1

y = x; // statement 2

x++; //statement 3

x = x + 1; // statement 4
 In the above four statements, only statement 1 is an atomic operation, which directly writes the value 10 to the working memory. To ensure the atomicity of non-atomic operations, you can use the synchronized keyword and Lock explicit locks to achieve atomicity of the entire operation.

 

non-atomic agreement

The above-mentioned read and write operations on variables of basic types are atomic operations, but they are not necessarily satisfied for 64-bit data types long and double . Because a loose regulation is specially defined in the JMM memory model: the JVM virtual machine is allowed to divide the read and write operations of 64-bit data that are not modified by volatile into two 32-bit operations. 

Therefore, the read and write operations on variables of type long and double are not guaranteed to be atomic operations, which is the so-called non-atomic contract between long and double. So when multiple threads read or modify a long or double variable that is not declared volatile at the same time, some threads may read a value that is neither the original value nor the representative of the modified value of other threads. "Half a variable" value, of course this is very rare. Because JVM virtual machines on most platforms still choose to implement the read and write operations of 64-bit data as atomic operations.

 

 

To sum up

The synchronized keyword and Lock objects support atomicity, ordering, and visibility at the same time. 

The volatile keyword only supports visibility and ordering, and does not guarantee atomicity.

 

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=326080765&siteId=291194637