Understanding of the volatile keyword for Java concurrency programming
Each thread in Java has its own working memory, analogous to the Processor's cache, where the Thread's working memory holds a copy of the main memory of the variable used by that Thread. Thread read and write variables are directly in their own working memory, and when to refresh the data (refers to the modified results to main memory or the main memory of the variable read to overwrite the value in the Work) is not deterministic.
The volatile keyword is a modifier field of the keyword, seemingly JDK1.5, in multithreaded programming, a great chance to use this keyword, volatile modified variable after the variable has such an effect: every time the thread reads the variable is directly from main memory (the main memory of the Jvm) read, Rather than from the working memory of the thread; each time the variable is written, it is written in main memory, not just in the Thread's working Ram. So the beginning of the "when refresh data is indeterminate" applies only to Non-volatile Variables.
The JVM has two guarantees for volatile variables:
-
Visibility. The is probably explained above, that is, one thread changes the value, and the other thread can read the changed value immediately and it is easy to understand.
-
happens-before. there are two points to note:
When a thread writes a volatile variable, the write to the volatile variable will be written to main memory, not just the working memory, if a normal variable is written to it, and the thread reads the volatile variable. If the reading of a common variable is read on the volatile variable, then the reading of the common variable will be synchronized with main memory and then read, rather than read directly from the working memory. For example, Download
Java code
Thread A:
Object.nonvolatilevar = 1; //stepA1
Object.volatilevar = Object.volatilevar + 1; //stepA2
Thread B:
int Volatilevar = object.volatilevar; //stepB1
int nonvolatile = object.nonvolatilevar; //stepB2
When thread a executes to stepA2, when the new value of Volatilevar is written to main memory, the new value of Nonvolatilevar is also brushed into main memory, and when thread B executes to stepB1, When you want to read Object.volatilevar from main memory, Object.nonvolatilevar is also read into the working memory together, so when thread B executes to StepB2, it can get the latest value of nonvolatilevar. This feature is actually useful: when a thread has more than one volatile variable, you can reduce the volatile variable (by reading and writing the variable), and you can achieve the same effect as multiple volatile variables.
Read-write instructions for volatile variables are not reordered by the Jvm. Other instructions before or after the read/write can be reordered, but the relative order of the read/write instructions and other instructions for the volatile variable will not change. For example, Download
Java code
Object.nonvolatile1 = 123; //instruction1
Object.nonvolatile2 = 456; //instruction2
Object.nonvolatile3 = 789; ////instruction3
Object. volatile = true; //a volatile Variable,//instruction4
int value1 = sharedobject.nonvolatile4; //instruction5
int value2 = sharedobject.nonvolatile5; //instruction6
int value3 = sharedobject.nonvolatile6; //instruction7
Since the JVM discovers that instruction1, instruction2, and Instruction3 have no Back-and-forth relationships, the JVM may reorder the three instructions, instruction456, but there is a volatile variable in the middle of the READ. So instruction123 is not reordered to the back of instruction4, the same instruction456 will not be reordered to instruction4, their relative order will not change.
A very common example of volatile is the singleton pattern (some thread-safe notation): Download
Java code
public class Singleton {
Private volatile Static Singleton instance;
public Static Singleton getinstance () {
if (instance = = null) { //step1
synchronized (Singleton. class) { //step2
if (instance = = null) { //step3
Instance = New Singleton (); //STEP4
}
}
}
return instance;
}
Private Singleton () {}
}
If the isntance here is not volatile, then this single case is non-multithreaded security, knowing that synchronized has a visibility guarantee may ask: why is it used here synchronized also need to use volatile modification? indeed, both are guaranteed to be visible, but this is not because of the visibility, but because of the reason for the order reordering: the first thing to know is that the new object has three steps (pseudo code): Download
Java code
Memory = Allocate (); //1: allocating the Object's memory space
Ctorinstance (memory); //2: Initialize Object
Instance = memory; ///3: Set instance to point to the memory address just allocated
And these three instructions are certainly the same thread execution, according to Intra-thread semantic (intra-thread semantics ensure that reordering does not change the execution of the program in a single thread), these three instructions can be re-ordered to the following:
Java code
-
memory = allocate (); //1: allocating the Object's memory space
-
instance = Memory; //3: set instance to point to the memory address just allocated
-
ctorinstance ( memory); //2: Initialize Object
Then there is a problem with the single case Above. Assuming unfortunately the above reordering occurred, then the thread that initialized the object just set instance = Memory (I.E. instance is not already null) but when instance is not initialized, another thread runs to Step1 and discovers instance is not null , and then directly take the instance to use, the latter will naturally appear a variety of problems, because the object has not been initialized at All. With the volatile modifier, the above-mentioned reordering is Banned.
java.util.concurrent package, such as java.util.concurrent.futuretask<t> There are happens-before principles for using volatile:: download
650) this.width=650; "src=" http://dl2.iteye.com/upload/attachment/0119/5240/ 96175d72-d0ce-37ba-ae8a-a379dc0d9ad6.png "class=" magplus "width=" "title=" Click to view original size picture "height=" 365 "style=" border : 0px; "/>
650) this.width=650; "src=" http://dl2.iteye.com/upload/attachment/0119/5242/ 0a7dfced-31a0-3b2e-9629-3ca59a221264.png "class=" magplus "width=" "title=" Click to view original size picture "height=" 281 "style=" Border : 0px; "/>
You can see that there are two variable state, and the callable need to ensure its visibility, but only one is decorated with volatile, and the order of writing guarantees the visibility of the variable that is not modified by the Volatile.
The book read: "in addition to volatile, synchronized and final can also achieve visibility." Synchronized visibility: before leaving the synchronized code block, you must first synchronize the variables into main memory. Final Visibility: The final decorated field is initialized once in the constructor, and the constructor does not pass the this reference, which is seen in other THREADS.
The understanding of the volatile of Java concurrency programming