Khi tôi viết mã không đồng bộ bằng async / await, thường là ConfigureAwait(false)
để tránh nắm bắt bối cảnh, mã của tôi sẽ chuyển từ một chuỗi luồng này sang luồng tiếp theo sau mỗi chuỗi await
. Điều này làm tăng mối quan tâm về an toàn chủ đề. Mã này có an toàn không?
static async Task Main()
{
int count = 0;
for (int i = 0; i < 1_000_000; i++)
{
Interlocked.Increment(ref count);
await Task.Yield();
}
Console.WriteLine(count == 1_000_000 ? "OK" : "Error");
}
Biến i
này không được bảo vệ và được truy cập bởi nhiều luồng xử lý nhóm *. Mặc dù mô hình truy cập là không đồng thời, nhưng về mặt lý thuyết, mỗi luồng sẽ tăng giá trị được lưu trong bộ nhớ cache cục bộ i
, dẫn đến hơn 1.000.000 lần lặp. Tôi không thể tạo ra kịch bản này trong thực tế. Mã ở trên luôn in OK trong máy của tôi. Điều này có nghĩa là mã là chủ đề an toàn? Hoặc tôi nên đồng bộ hóa quyền truy cập vào i
biến bằng cách sử dụng a lock
?
(* một chuyển đổi luồng xảy ra trung bình cứ sau 2 lần lặp, theo các thử nghiệm của tôi)
i
là lưu trữ trong mỗi chủ đề? Xem điều này SharpLab IL để đào sâu hơn.