Se si dispone di una variabile condivisa (ad esempio, come campo statico di una classe o come campo di un oggetto condiviso), e tale campo o oggetto verrà utilizzato per il cross-thread, quindi, sì, si è necessario assicurarsi che l'accesso a tale variabile sia protetto tramite un'operazione atomica. Il processore x86 ha caratteristiche intrinseche per assicurarsi che ciò accada, e questa funzionalità è esposta attraverso i metodi di classe System.Threading.Interlocked.
Ad esempio:
class Program
{
public static Int64 UnsafeSharedData;
public static Int64 SafeSharedData;
static void Main(string[] args)
{
Action<Int32> unsafeAdd = i => { UnsafeSharedData += i; };
Action<Int32> unsafeSubtract = i => { UnsafeSharedData -= i; };
Action<Int32> safeAdd = i => Interlocked.Add(ref SafeSharedData, i);
Action<Int32> safeSubtract = i => Interlocked.Add(ref SafeSharedData, -i);
WaitHandle[] waitHandles = new[] { new ManualResetEvent(false),
new ManualResetEvent(false),
new ManualResetEvent(false),
new ManualResetEvent(false)};
Action<Action<Int32>, Object> compute = (a, e) =>
{
for (Int32 i = 1; i <= 1000000; i++)
{
a(i);
Thread.Sleep(0);
}
((ManualResetEvent) e).Set();
};
ThreadPool.QueueUserWorkItem(o => compute(unsafeAdd, o), waitHandles[0]);
ThreadPool.QueueUserWorkItem(o => compute(unsafeSubtract, o), waitHandles[1]);
ThreadPool.QueueUserWorkItem(o => compute(safeAdd, o), waitHandles[2]);
ThreadPool.QueueUserWorkItem(o => compute(safeSubtract, o), waitHandles[3]);
WaitHandle.WaitAll(waitHandles);
Debug.WriteLine("Unsafe: " + UnsafeSharedData);
Debug.WriteLine("Safe: " + SafeSharedData);
}
}
I risultati:
Unsafe: -24.050,275641 millions sicuro: 0
In una nota interessante, mi sono imbattuto questo in modalità x64 su Vista 64. Questo mostra che i campi a 64 bit vengono trattati come campi a 32 bit dal runtime, ovvero le operazioni a 64 bit non sono atomiche. Qualcuno sa se questo è un problema CLR o un problema x64?
Per le operazioni atomiche su Int64, è possibile utilizzare la classe InterLocked (http://msdn.microsoft.com/en-us/library/system.threading.interlocked.add.aspx). –