Tăng/giảm không được bảo vệ không an toàn theo chủ đề - và do đó không phải là nguyên tử giữa các chuỗi. (Mặc dù nó có thể là "nguyên tử" WRT IL thực tế/ML chuyển .)
LINQPad mã ví dụ này cho thấy kết quả không thể đoán trước:
void Main()
{
int nWorkers = 10;
int nLoad = 200000;
int counter = nWorkers * nLoad;
List<Thread> threads = new List<Thread>();
for (var i = 0; i < nWorkers; i++) {
var th = new Thread((_) => {
for (var j = 0; j < nLoad; j++) {
counter--; // bad
}
});
th.Start();
threads.Add(th);
}
foreach (var w in threads) {
w.Join();
}
counter.Dump();
}
Lưu ý rằng khả năng hiển thị giữa các chủ đề có tầm quan trọng . Đồng bộ hóa đảm bảo khả năng hiển thị này ngoài nguyên tử.
Mã này dễ dàng được sửa, ít nhất trong ngữ cảnh giới hạn được trình bày.Chuyển ra sụt lần và quan sát kết quả:
counter--; // bad
Interlocked.Decrement(ref counter); // good
lock (threads) { counter--; } // good
Ngay cả khi sử dụng một biến volatile
, kết quả là vẫn không thể đoán trước. Điều này dường như chỉ ra rằng (ít nhất ở đây, khi tôi chỉ chạy nó) nó cũng là không một nhà điều hành nguyên tử như đọc/op/ghi của các chủ đề cạnh tranh được xen kẽ. Để thấy rằng hành vi này là vẫn không chính xác khi các vấn đề tầm nhìn được loại bỏ (chúng là gì?), Thêm
class x {
public static volatile int counter;
}
và sửa đổi các mã trên sử dụng x.counter
thay vì biến counter
địa phương.
Câu hỏi hay hơn là khả năng, là gì * sử dụng * 'idleAgents' đồng thời an toàn? – user2246674
có thể trùng lặp của [Nguyên tắc toán tử ++ có an toàn không?] (Http://stackoverflow.com/questions/4628243/is-the-operator-thread-safe) – nawfal