Directory
Singleton example
Volatile solution 1: CPU Cache
Volatile solution 2: Compiler Optimization (command out-of-order)
I. standard Singleton mode example ''' csharppublic sealed class Singleton {// static instance Private Static volatile Singleton instance = NULL; // lock object, private Static object syncroot = new object (); used for thread security ();
Private Singleton () {} public static Singleton instance {get {If (instance = NULL) // compare {lock (syncroot) {If (instance = NULL) // second comparison instance = new Singleton () ;}} return instance ;}}
}
'''
Note: The modifier before the Automatic Static example: Volatile. Why must I specify volatile? If this keyword is not used, what are the consequences.
Volatile [changeable]. Check the msdn: Volatile keyword to indicate that a field can be modified by multiple concurrent threads. Fields declared as volatile are not restricted by Compiler Optimization (assuming that they are accessed by a single thread. This ensures that the field displays the latest value at any time.
So what happened at the underlying layer? Don't you use volatile? Isn't the field value new during Command Execution? It should begin with two aspects: computer architecture and compiler optimization.
Ii. CPU cache Problems
The volatile keyword is used. Each time a field value is read, it must be obtained from the memory. That is, CPU cache is disabled for this field.
Because the modern CPU has multiple cores, each core has an independent internal cache, and the object field is originally stored in the memory, before executing the command, check whether this field exists in the cache. If no, read data from the memory to the CPU cache for calculation. If the cache exists, you do not need to access the memory and directly use the cached data.
For the singleton mode example, the two threads run on two CPU cores respectively, and the two cores run on the preceding statement "first comparison" simultaneously. The instance field is saved in the internal cache of each CPU, with the lock keyword, the two threads execute the lock statement block in a serial manner.
For example, if core A has completed the lock statement block and the instance in the memory has been updated, core B continues to run. Because core B has cached the instance example, during the second comparison, we still think that the instance field is null, which causes new Singleton () to be executed twice.
Iii. Compiler Optimization Problems
Using the volatile keyword can avoid instruction reordering. For example, consider the following loop: '''csharpwhile (true) {If (myfield) {// do something }}
'''
If volatile is not specified for the myfield field, during JIT compilation, the compiler re-sorts the command as follows for performance optimization considerations: '''csharp
If (myfield) {While (true) {// do something }}
'''
In this case, if you modify the field myfiled in another thread, the running result will be different. Generally, the lock Statement (Monitor. Enter/monitor. Exit) is recommended. However, if you modify only one field in this statement block, volatile will have better performance.