Monday, November 28, 2005

.NET Volatile Field

The MSDN description for the volatile modifier:
"For non-volatile fields, optimization techniques that reorder instructions can lead to unexpected and unpredictable results in multi-threaded programs that access fields without synchronization such as that provided by the lock-statement."

What does it mean? In a multi-CPU and multi-threaded environment, a value could be temporarily stored in registers and multiple levels of cache, and the value change by a thread in one CPU may not be seen immediately by another thread run in another CPU. This could lead to some unpredictable issues.

We can guarantee to get a refresh value by declaring a volatile field:
using System;
using System.Threading;
class Test
{
public static bool finished = false;
private static object syncLock = new object();
static void Main()
{
new Thread(new ThreadStart(Thread1)).Start();
new Thread(new ThreadStart(Thread2)).Start();
Console.Read();
}
static void Thread1()
{
while (true)
{
if (finished)
{
Console.WriteLine("Finished.");
break;
}
}
}
static void Thread2()
{
lock (syncLock)
{
finished = true;
}
}
}
In above code snippet, Thread1 will immediately see the latest "finished" value updated by a Thread2, and guarantee to finish and break the infinite loop. Without volatile declared, Thread1 could (not always) never be ended in some systems.

One important note is that volatile field doesn't mean it's thread-safe. Locking mechanism is still required in some scenarios. With a locked field, the value of that field is guarantee to be the latest one, and volatile is unnecessary in such case.

(Updated 2006/9):
My original understanding may not be correct. Some people argue that volatile only means the sequence of accessing a volatile member won't reordered, it doesn't mean that a value assignment will be immediately visible to all processors. However I could not verify this without a real environment.