Dark Horse Programmer:Java Training, Android training, iOS training,. NET Training
Java threading-memory models and volatile explanations
One, single core memory model
1. When the program runs, the temporary data is stored in the cache
2. Copy the data needed for CPU calculation from cache to h cache
3, the CPU directly from the H cache read data to calculate
4. The CPU writes the computed results to h cache
5. H cache will rinse the latest result value into the cache (when write is indeterminate)
6. Write back the result data in the cache to the program (if necessary, such as files, databases)
The reason for the H cache is that the CPU executes very fast, while reading or writing data to the cache is much slower, so the H cache is needed to compensate.
Second, multicore memory model
There are 2 threads: Threada and THREADB, respectively, running in different cups and executing the following code:
i = 0; i = i + 1;. Finally, we want the value of I to be 2.
1, Threada and threadb respectively read the value of i=0 into the respective H cache, at this time the H cache in the I value of 0;threada and threadb respectively to calculate and the results are 1; 2 h caches write the results to the cache respectively. Finally, the value of I in cache is 1. Obviously, this is not the result we want to get. This is the famous: Cache consistency issue. (The same problem occurs for single-core CPUs, except that single-core CPUs are executed separately in the form of thread scheduling)
2. How to solve the problem of cache consistency
1) bus plus lock# lock (inefficient, non-fetching)
2) Cache Consistency Protocol (not detailed here)
Iii. Three concepts of concurrency
1. Atomic Nature
1) that is, an operation or multiple operations, or all execution and execution of the process will not be interrupted by any factors, or do not execute.
2) has the following code: i = 9999999999;
Suppose a 32-bit variable is assigned a value of 2 procedures: a low 16-bit assignment, and a high 16-bit assignment. Now, it can happen: Threada writes a low 16-bit value after it is suddenly interrupted, and threadb reads the value of I to get the wrong result.
2. Visibility
1) means that when multiple threads access the same variable, a thread modifies the value of the variable, and other threads can immediately see the modified value.
2) Threada and THREADB execute the following code, respectively:
Threada:int i = 0;
i = 10;
Threadb:int j = i;
(1) When Threada executes to i=10, it first loads the initial value of I into the H cache of its CPU and assigns a value of 10. Then, the value of I in Threada's H cache is 10, but Threada does not immediately write the value of I in H cache immediately to the cache.
(2) At this point, the threadb starts executing, but the value of I in the cache is still 0, and eventually, the value of J is 0 anyway. Instead of what we want j=10 to do.
(3) This is precisely because Threada to I modified, THREADB did not immediately see the thread Threada to I modified value.
3. Orderly Nature
1) The order in which the program executes is executed in the order of the Code.
2) Order reordering: That is, the processor in order to improve the efficiency of the program, the input code may be optimized, it does not guarantee that the execution sequence of the individual statements in the program is consistent with the order in the code, but it will ensure that the results of the final execution of the program and code sequence execution results are consistent.
3) have the following code:
int a = 10; Statement 1
int r = 2; Statement 2
A = a + 3; Statement 3
R = A * A; Statement 4
Possible order of execution: 1 2 3 4 or 2 1 3 4, no longer possible. This is because the processor needs to consider the data dependencies between the instructions.
4) Threada and THREADB execute the following code, respectively:
Threada:context = Loadcontext (); Statement 1
inited = ture; Statement 2
Threadb:while (!inited) sleep (); Statement 3
DoSomething (context); Statement 4
If the processor Threada instructions, threadb may execute dosomething (context) without assigning a value to the context, causing the program to run incorrectly.
As can be seen, atomicity, visibility, and ordering do not affect the execution of code by a single thread. However, the correctness of concurrent execution is shadow. If you want the program to execute correctly, you must also ensure atomicity, visibility, and ordering.
Iv. Java to ensure the correctness of concurrent execution
1. Atomic Nature
1) in Java, read and assign operations to variables of the base data type are atomic.
2) Which of the following statements are atomic operations
x = 10; is atomic operation
x = x + 1; Not: First read x value, plus 1, last assignment
x + +; Not: First read x value, plus 1, last assignment
y = x; Not: First read the x value, then assign the value
3) If you achieve a wider range of atomicity, you can use synchronized and lock to achieve this.
2. Visibility
1) Use volatile to ensure visibility: the modified value is guaranteed to be updated immediately to the cache and invalidates the value of the volatile variable in the h cache of other threads.
2) You can also use synchronized and lock to ensure visibility: the modified value is guaranteed to be updated to the cache before the lock is released and invalidates the value of the related variable in the h cache of other threads.
3. Orderly Nature
1) Use volatile to ensure true ordering: Prohibit command reordering of volatile variables.
2) synchronized and lock also ensure that the order is implemented as a single-threaded execution of a synchronous block of code.
A detailed discussion of volatile variables
1. The two meanings of the volatile keyword:
1) Assurance of visibility
2) Prohibit order reordering, ensure the order of
(1) When a volatile variable is read or written, the operation in front of the volatile variable is already complete and the result is already visible to the current operation, and the post-operation of the current operation must not be executed.
(2) When the instruction is optimized, the instructions before the operation of the volatile variable cannot be placed after the volatile variable, nor can the instructions after the operation of the volatile variable be executed before the volatile variable.
Note: The volatile keyword does not guarantee atomicity
3) For example:
x = 9; Statement 1
y = 8; Statement 2
volatile flag = ture; Statement 3
i = 7; Statement 4
K = 6; Statement 5
Although there is no dependency between X,Y,I,J, Statement 4 and statement 5 will not be placed before statement 3 and statement 1 and statement 2 will not be executed after statement 3.
The possible order of execution is: 1,2,3,4,5 or 2,1,3,4,5, or 1,2,3,5,4
or 2,1,3,5,4
2. The difference between volatile and synchronized
1) Common Ground
(1) Both volatile and synchronized are part of the synchronization mechanism
(2) Visibility and ordering are achieved
2) Differences
(1) Synchronized achieves atomicity, and volatile does not
(2) The object of action is different: the volatile action is the variable, and the synchronized action is the statement block or method.
(3) The role of the thread is different: volatile does not block the thread, and synchronized blocks the thread, that is, volatile does not use the monitor, and synchronized uses the monitor. Therefore, volatile is a more lightweight, less-than-synchronized synchronization mechanism.
Vi. correct use of volatile
1. Mode one: status mark
1) No concurrency problems caused by using volatile
Threada:boolean stop = false; Threadb:stop = ture;
while (!stop) {
A
DoSomething ();
}
Concurrency may not be performed correctly: that is, Threada into the dead loop
Cause: 1, Threada always read only the value of stop in H cache
2. threadb only saves the value of the modified stop to its H cache
3, even if the Threada occasionally reads the value of stop from the cache, if the thread is blocked at a
Plug, and at this point threadb modifies the stop value and writes to the cache, because Threada does not see that the stop value in the cache has been modified, it may go into a dead loop even if it is re-executed.
2) use volatile to resolve
Threada:boolean stop = false; Threadb:stop = ture;
while (!stop) {
A
DoSomething ();
}
2, Mode two: Double-check (in the single case mode of use)
Private volatile static Singleton instance;
Public stratic Singleton getinstance () {
if (instance = = null) {
Synchronized (Singleton.class) {
if (instance = = null) {instance = new Singleton ();}
}
}
}
This is a classic case where volatile is used in conjunction with synchronized.
3. Mode three: Low overhead read-write lock policy
public class cheesycounter{
All mutative operations Msut is done with the ' this ' lock held
@GuardedBy ("This") private volatile int value;
public int Getvulue () {return value;}
public synchronized int increment () {return value++;}
}
1) Another classic case where volatile and synchronized are used together
2) If the read operation is much more than the write operation, you can use a combination of lock and volatile variables to reduce the overhead of the common code path, such as this example.
3) The counter must use synchronized to ensure that the incremental operation is atomic, while using volatile to guarantee the visibility of the current result.
4) If the update is infrequent, the read overhead involves only volatile operations, due to the overhead of a no-compete lock acquisition.
Comments on the Web: This mode value does not use volatile can also achieve threadsave, because increment ()
Using the synchronized, is that really the case? The answer is no, if Threada is in.
Line Increment (), note that synchronized only implements mutually exclusive access to increment () and does not implement mutually exclusive access to value, and threadb is also doing getvulue (), Then THREADB will have a value that is invalid because THREADB does not know that Threada is modifying the value.
4, Mode four: one-time security release, publish immutable objects or thread-safe objects
public class test{
public volatile Finalobject object;
public void CreateObject () {object = new Finalobject (...);}//threada
public void DoWork () {//threadb
while (ture) {//polling
if (Object! = null) {DoSomething (object);}
}
}
}
1) Publish: Enables objects to be used in code outside the scope of the current thread.
2) If the object reference is not a volatile type, the doWork () reference to object may get a finalobject that is not fully constructed.
3) It is important to note that the object itself must be thread-safe.
4) volatile types ensure that the form of publication is visible, but if the state of object is mutable after it is published, additional synchronization is required.
5) This case also shows that blocking the execution of another thread without using blocking (although this is not a real block, but acts as a blocking function).
Online Comment: Volatile is not sufficient for secure publishing because object may be interrupted during construction. We should remember that volatile has a very important feature: it prohibits command reordering of volatile variables. That is, the interrupt instruction is either executed before the object is constructed, or it is executed after the object is constructed, and cannot occur during the construction process.
5, Mode five: Independent observation
public class usermanager{
public volatile String Lastuser;
public Boolean authenticate (string userName, string password) {
Boolean valid = passwordisvalid (user, password);
if (valid) {
User U = New user (userName, password);
Activeusers.add (U);
Lasstuser = user;
}
return valid;
}
.........
}
1) This example shows how the identity mechanism remembers the name of the last logged-on user, and uses Lastuser to publish values repeatedly for use by other parts of the program.
2) Another use of this mode is to collect statistical information about the program or to publish information periodically (irregularly)
3) This mode requires: (1) The published value is valid immutable-that is, the status of the value will not change after publication (the next release is already a new value, not a change based on the original value)
(2) code that uses published values needs to be clear that the value may change at any time.
6, Mode six: Volatile-bean mode
@ThreadSafe
public class person{
private volatile stirng name;
private volatile int age;
Public String GetName () {return name;}
public int getage () {return age;}
public void SetName (String name) {this.name = name;}
public void Setage (int.) {this.age = age;}
}
1) Principle: Many frameworks provide containers for variable data holders (such as httpsession), but the objects placed in these containers must be thread-safe.
2) All members of the Volatile-bean mode must be volatile and valid, while only getter and setter methods are available.
Four, the use of volatile variables principle
1, the Write variable does not depend on the value of this variable, or only one thread modifies this variable
2. Variables do not participate in invariant constraints with other variables
3, Access variables do not need to lock
Dark Horse-----Memory model and volatile explanation