Nếu bạn có biến chia sẻ (ví dụ như trường tĩnh của một lớp hoặc trường của đối tượng được chia sẻ) và trường hoặc đối tượng đó sẽ được sử dụng cross-thread, thì, vâng, bạn cần đảm bảo rằng quyền truy cập vào biến đó được bảo vệ thông qua hoạt động nguyên tử. Bộ vi xử lý x86 có nội tại để đảm bảo điều này xảy ra và cơ sở này được hiển thị thông qua các phương thức lớp System.Threading.Interlocked.
Ví dụ:
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);
}
}
Kết quả:
không an toàn: -24050275641 Safe: 0
Trên một mặt lưu ý thú vị, tôi chạy này ở chế độ x64 trên Vista 64. Điều này cho thấy các trường 64 bit được xử lý như các trường 32 bit theo thời gian chạy, nghĩa là các hoạt động 64 bit không phải là nguyên tử. Bất cứ ai biết nếu đây là một vấn đề CLR hoặc một vấn đề x64?
Đối với các hoạt động nguyên tử trên Int64, bạn có thể sử dụng lớp InterLocked (http://msdn.microsoft.com/en-us/library/system.threading.interlocked.add.aspx). –