C # 2.0 Characteristics: Volatile
volatile
Keyword indicates thread modifies a field that can be executed simultaneously by multiple. For performance reasons, compilers, runtime system hardware may even rearranged to read and write memory locations. Declared volatile
field without these optimizations. Adding volatile
modifier to ensure a consistent order of execution of the writing operation and the sequence was observed when all threads observed volatile write operation (performed by any other thread). It does not ensure that all volatile write operations are by ordering the execution order when all threads of execution from the whole.
volatile
Keywords can be applied to the following types of fields:
- Reference type.
- Pointer type (in an unsafe context). Note that although the pointer itself can be variable, but it points to an object can not be a variable. In other words, it can not be declared "variable pointing to an object pointer."
- Simple type, such as
sbyte
,byte
,short
,ushort
,int
,uint
,char
,float
andbool
. - It has one of the following basic types of types:
enum
, , , , or .byte
sbyte
short
ushort
int
uint
- It is known as reference types of generic type parameter.
- IntPtr 和 UIntPtr。
Other types (including double
and long
) not marked volatile
as read and write to these types of fields can not be guaranteed to be atomic. To protect multi-threaded access to these types of fields, use the Interlocked class members or use the lock
statement to protect access.
volatile
Keywords can only be applied class
or struct
fields. Local variables can not be declared volatile
.
The following example shows how a variable declared as public fields volatile
.
class VolatileTest { public volatile int sharedStorage; public void Test(int _i) { sharedStorage = _i; } }
The following example shows how to create a secondary thread, and use it with the main thread executed in parallel processing.
1 public class Worker 2 { 3 // This method is called when the thread is started. 4 public void DoWork() 5 { 6 bool work = false; 7 while (!_shouldStop) 8 { 9 work = !work; // simulate some work 10 } 11 Console.WriteLine("Worker thread: terminating gracefully."); 12 } 13 public void RequestStop() 14 { 15 _shouldStop = true; 16 } 17 // Keyword volatile is used as a hint to the compiler that this data 18 // member is accessed by multiple threads. 19 private volatile bool _shouldStop; 20 } 21 22 public class WorkerThreadExample 23 { 24 public static void Main() 25 { 26 // Create the worker thread object. This does not start the thread. 27 Worker workerObject = new Worker(); 28 Thread workerThread = new Thread(workerObject.DoWork); 29 30 // Start the worker thread. 31 workerThread.Start(); 32 Console.WriteLine("Main thread: starting worker thread..."); 33 34 // Loop until the worker thread activates. 35 while (!workerThread.IsAlive) 36 ; 37 38 // Put the main thread to sleep for 500 milliseconds to 39 // allow the worker thread to do some work. 40 Thread.Sleep(500); 41 42 // Request that the worker thread stop itself. 43 workerObject.RequestStop(); 44 45 // Use the Thread.Join method to block the current thread 46 // until the object's thread terminates. 47 workerThread.Join(); 48 Console.WriteLine("Main thread: worker thread has terminated."); 49 } 50 // Sample output: 51 // Main thread: starting worker thread... 52 // Worker thread: terminating gracefully. 53 // Main thread: worker thread has terminated. 54 }
The volatile
adding a modifier to _shouldStop
the statement will always get the same result (similar to the previous code fragment shown). However, if _shouldStop
no member of the modifier on the behavior is unpredictable. DoWork
The method may optimize the member access, resulting in reading stale data. Given the nature of multi-threaded programming, number of reads stale data is unpredictable. Different programs run will produce some different results.