There are three very important features in concurrent programming : Atomicity , Order ,, visibility , My sister found out you didn't know them very well , She was in a hurry , Because understanding these three features is very helpful to develop high concurrency programs correctly , It's also likely to be asked in the next interview , I can't help but start to introduce them to you one by one .

<>Java Memory model

Before we talk about the three features, let's briefly introduce them Java Memory model (Java Memory Model, abbreviation JMM), Got it Java After memory model , Three characteristics can be better understood .

Java Memory model is an abstract concept , It's not real , It describes a set of specifications or regulations .JVM The entity running the program is a thread , Each thread has its own private working memory .Java The memory model specifies that all variables are stored in main memory , Main memory is a shared memory area , All threads have access . However, the reading and assignment of variables by threads must be carried out in their own working memory , Copy variables from main memory to working memory before operation , Then operate on the variables , Write variables back to main memory after operation . Threads cannot directly operate on variables in main memory , The working memory of a thread holds a copy of the variables in main memory .

<> Atomicity (Atomicity)

<> What is atomicity

Atomicity means : During one or more operations , Or all operations are performed , Or all operations will not be performed .

When it comes to atomicity, we usually use bank transfer as an example , For example, Zhang San transfers money to Li Si 100 Yuan , This involves two atomic operations : Decrease on Zhang San's account 100 Yuan ; Add to Li Si's account 100 Yuan . These two operations must meet the requirements of atomicity , Or they all work , Or both fail . No account decrease of Zhang San 100 Yuan, but Li Si's account didn't increase 100 Yuan , It can't be that Zhang San's account hasn't been reduced 100 Yuan, but Li Si's account has increased 100 Yuan .

<> Atomic example

<> Example 1
i = 1;
According to the above Java Memory model , Thread first i=1 Write to working memory , And then write it into main memory , The assignment statement is atomic .

<> Example 2
i = j;

This assignment actually involves two steps : Thread reads from main memory j Value of , It is then stored in the working memory of the current thread ; Threads put the i Change to j Value of , And then i The value of is written to main memory . Although both of these steps are atomic operations , But together, it's not an atomic operation .

<> Example 3
i++;

This auto increment operation actually consists of three steps : Thread reads from main memory i Value of , It is then stored in the working memory of the current thread ; Threads put the i Executive plus 1 operation ; Thread again i The value of is written to main memory . Same as the previous example , Although these three steps are atomic operations , But together, it's not an atomic operation .

From the three examples above , We can find out : Simple read and assign operations are atomic , But assigning one variable to another is not atomic ; Multiple atomic operations put together are not atomic .

<> How to guarantee atomicity

stay Java In memory model , Only atomic operation of basic reading and assignment is guaranteed . If you want to guarantee the atomicity of multiple operations , Need to use synchronized Keywords or Lock
Related tool classes . If you want to make int,long The same type of self increasing operation has atomicity , It can be used java.util.concurrent.atomic Tool class under package , as :
AtomicInteger,AtomicLong etc . Also note that ,volatile Keywords do not have atomic semantics .

<> visibility (Visibility)

<> What is visibility

Visibility means : When a thread modifies a shared variable , Another thread can immediately see the latest modified value of the variable .

<> Visibility example
package onemore.study; import java.text.SimpleDateFormat; import java.util.Date
; public class VisibilityTest { public static int count = 0; public static void
main(String[] args) { final SimpleDateFormat sdf = new SimpleDateFormat(
"HH:mm:ss.SSS"); // read count Thread of value new Thread(() -> { System.out.println(
" Start reading count..."); int i = count;// deposit count Value before update of while (count < 3) { if (count !=
i) {// When count When the value of , Printing count Updated System.out.println(sdf.format(new Date()) + "
count Updated to " + count); i = count;// deposit count Value before update of } } }).start(); // to update count Thread of value new
Thread(() -> { for (int i = 1; i <= 3; i++) { // every other 1 Seconds are count Assign a new value try { Thread.
sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } System.
out.println(sdf.format(new Date()) + " assignment count by " + i); count = i; } }).start();
} }

Before running the code , Let's think about the output of the run ? Updating count In thread of value , Every update count in the future , Reading count There will be one output in the thread of value ? Let's take a look at what the run output is :
Start reading count... 17:21:54.796 assignment count by 1 17:21:55.798 assignment count by 2 17:21:56.799
assignment count by 3

From the output of operation, we can see that , read count Value has not been read by the thread count Latest value of , Why is that ? Because reading count In thread of value , First read count Value , Read from main memory count Write the value of to your own working memory , Read from working memory , Read after count Values are read from their own working memory , No updates found count Thread pair for value count Value modification .

<> How to ensure visibility

stay Java The following can be used in 3 Ways to ensure visibility .

<> use volatile keyword

When a variable is volatile
When keyword is decorated , Other threads modify this variable , Invalidates the variable copy of the current thread in working memory , Must get from main memory again , After the current thread modifies variables in working memory , At the same time, it will immediately refresh its modification to main memory .

<> use synchronized keyword

synchronized Keyword can ensure that only one thread gets lock at the same time , Then execute the synchronization method or code block , And make sure that before the lock is released , Changes to variables will be refreshed to main memory .

<> use Lock Related tool classes

Lock Related tool class lock Method can ensure that only one thread gets lock at the same time , Then execute the synchronization code block , And make sure Lock Related tool class unlock
Method before , Changes to variables will be refreshed to main memory .

<> Order (Ordering)

<> What is order

Order means : The order of program execution is the order of code execution .

stay Java in , In order to improve the efficiency of the program , The code instructions may be optimized during compilation and runtime , There is no 100% guarantee that the code will be executed strictly in the order in which it was written , But it's not a random reorder , It will ensure that the final operation result of the program is what the code expects . This situation is called
Command rearrangement (Instruction Reordering).

<> Ordering example
package onemore.study; public class Singleton { private Singleton (){} private
static boolean isInit = false; private static Singleton instance; public static
SingletongetInstance() { if (!isInit) {// Judge whether it has been initialized instance = new Singleton();
// initialization isInit = true;// Initialization ID is assigned as true } return instance; } }
This is an example of a problematic singleton pattern , If the instructions are rescheduled at compile time or runtime , hold isInit = true; Reorder to instance = new Singleton();
In front of . At single thread run time , The execution result after program rearrangement is exactly the same as that after code sequence execution , But when multiple threads execute together, there is a high probability of problems . such as , A thread judges first isInit
by false Initialize , It should have been initialized before isInit Assigned as true, But because the instruction rearrangement is not initialized, the isInit
Assigned as true, At this time, another thread is judging whether it has been initialized ,isInit by true It's back instance, This is an uninitialized instance
, It's bound to make unpredictable mistakes .

<> How to ensure order

I want to mention it here Java One of the memory models is called antecedent (Happens-Before) The principle of . If the order of execution of the two operations cannot be changed from Happens-Before Principle pushed out , Then you can reorder them at will .Happens-Before What are the principles ?

* Principle of procedural order : The result of executing a piece of code in a single thread is orderly .
* Lock in principle : A lock is locked , Then it must be carried out first unlock Only after operation lock operation .
* volatile Variable principle : At the same time volatile Read and write variables , Write must precede read .
* Thread start principle :Thread Object's start Method precedes every action of this thread .
* Thread termination policy : All operations in a thread precede termination detection for this thread .
* Thread interrupt principle : To thread interrupt Method is called before the interrupted thread's code detects the occurrence of an interrupt event .
* Object termination principle : An object is initialized before its finalize Start of method .
* Transmission principle : operation A Prior to operation B, operation B Prior to operation C, Then operate A Must precede operation C.
except Happens-Before Natural order provided by principle , We can also guarantee the order in the following ways :

* use volatile Key words ensure order .
* use synchronized Key words ensure order .
* use Lock Relevant tool classes ensure order .
<> summary

* Atomicity : During one or more operations , Or all operations are performed , Or all operations will not be performed .
* visibility : When a thread modifies a shared variable , Another thread can immediately see the latest modified value of the variable .
* Order : The order of program execution is the order of code execution .
synchronized Keywords and Lock Related tool classes can guarantee atomicity , Visibility and order ,volatile Keywords ensure visibility and order , No guarantee of atomicity .

Technology
©2019-2020 Toolsou All rights reserved,
First knowledge python Skills summary GDOI2019 travels c Linguistic 5 Three common sorting methods Python Basic knowledge and notes " Cephalosporin wine Say go and go "? DANGER ! Don't drink alcohol when taking these drugs Thorough explanation from Zhongtai vue The component page height is adaptive according to the screen size Classical algorithm - recursion ( The case of raw rabbit ) Big data tells you , How tired are Chinese women about keras use fit_generator Encountered in StopIteration