Wenn Sie eine gemeinsam genutzte Variable haben (z. B. als statisches Feld einer Klasse oder als Feld eines gemeinsamen Objekts) und dieses Feld oder Objekt kreuzweise verwendet wird, dann ja Sie müssen sicherstellen, dass der Zugriff auf diese Variable über eine atomare Operation geschützt ist. Der x86-Prozessor verfügt über Intrinsics, um sicherzustellen, dass dies geschieht, und diese Funktion wird durch die System.Threading.Interlocked-Klassenmethoden verfügbar gemacht.
Zum Beispiel:
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);
}
}
Die Ergebnisse:
Unsafe: -24050275641 Sicher: 0
Auf interessante Randnotiz, lief ich diese im x64-Modus auf Vista 64. Dies zeigt, dass 64-Bit-Felder werden von der Laufzeit wie 32-Bit-Felder behandelt, dh 64-Bit-Operationen sind nicht atomar. Wer weiß, ob dies ein CLR-Problem oder ein x64-Problem ist?
Für atomare Operationen auf Int64 können Sie die InterLocked-Klasse (http://msdn.microsoft.com/en-us/library/system.threading.interlocked.add.aspx) verwenden. –