EXAMPLE CODE IS ON THE WAY ....
The C# Language contains the keyword volatile and I think this keyword is obsolete. Beside the fact that the using of volatile is often wrong and not necessary, the volatile keyword is often misinterpreted.
The volatile keyword gives often the wrong feeling of secure multithread code. Sometimes the volatile keyword is used to guarantee that a shared variable is not accessible from more than one thread during the same time.
BUT: The volatile keyword is not able to do this kind of service. The only way to protect a shared variable is to use a synchronization object (Monitor,Mutex) or the special static methods from the Interlocked class.
Why? I’ve a simple example to demonstrate the effect of the volatile keyword and an example to solve the problem. At the end I’m going to explain the volatile keyword and the case, when it is necessary to use volatile.
The example below shows the wrong use of the volatile keyword:
Two threads are started and both threads are operating with the shared variable counter. The shared variable counter is incremented by both threads. If everything is working fine, the result of the counter variable should be: ITERATION (const.) * Threads (in this case 2).
BUT: The counter variable is different from the expected value. Why? The keyword volatile is not helpful to guarantee thread-safety. In this case, the ++ Operation is not an atomicity operation. The volatile keyword guarantees that the “newest” value is reading from the memory and the value won’t be stored in a cache (L1, L2) but the value can be stored inside a CPU register.
What happens exactly?
The ++ Operation contains more than one instruction to complete the operation. The following Intermediate Language Code (IL) shows the necessary instruction for the ++ Operation.
As you can see, the operation needs three steps to complete:
- First: Load variable value (counter)
- Second: Do the calculation
- Third: Write back the result
On each operation it is possible that the thread will be interrupted. For example: A thread reads the variable counter and then the thread is interrupted, the variable value (counter) is stored inside the TIB (Thread Information Block). When the thread comes back to the processor (running again), the thread is using the stored value from the TIB. When a different thread has changed the value in the meantime, the old thread has no knowledge about this change. The re-activated thread is working with an old value. Writes the thread the value back to the memory, he overwrites the changes … Memory corrupted.
The volatile keyword is not enough and not necessary on a x86 Architecure based CPU with Cache Coherency (Strong Memory Model)
The only way to solve the problem is to use a lock or the Interlocked class methods.