Если у вас есть общая переменная (скажем, как статическое поле класса или как поле общего объекта), и это поле или объект будет использоваться перекрестным потоком, то да, вам нужно чтобы убедиться, что доступ к этой переменной защищен с помощью атомарной операции. Процессор x86 имеет встроенные функции, обеспечивающие это, и эта возможность предоставляется через методы класса System.Threading.Interlocked.
Например:
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);
}
}
Результаты:
Небезопасно : -24050275641
Сейф : 0
Что интересно, я запустил это в режиме x64 в Vista 64. Это показывает, что 64-битные поля обрабатываются как 32-битные поля во время выполнения, то есть 64-битные операции не являются атомарными. Кто-нибудь знает, если это проблема CLR или x64?