C# 4 in a Nutshell (rất khuyến khích btw) sử dụng đoạn mã sau để chứng minh các khái niệm về MemoryBarrier (giả sử A và B đã được chạy trên chủ đề khác nhau):Tại sao tôi cần một rào cản bộ nhớ?
class Foo{
int _answer;
bool complete;
void A(){
_answer = 123;
Thread.MemoryBarrier(); // Barrier 1
_complete = true;
Thread.MemoryBarrier(); // Barrier 2
}
void B(){
Thread.MemoryBarrier(); // Barrier 3;
if(_complete){
Thread.MemoryBarrier(); // Barrier 4;
Console.WriteLine(_answer);
}
}
}
họ đề cập rằng rào cản 1 & 4 ngăn chặn điều này ví dụ từ viết 0 và hàng rào 2 & 3 cung cấp bảo đảm độ tươi: chúng đảm bảo rằng nếu B chạy sau A, hãy đọc _complete sẽ đánh giá đúng.
Tôi không thực sự nhận được nó. Tôi nghĩ rằng tôi hiểu tại sao Rào cản 1 & 4 là cần thiết: chúng ta không muốn ghi vào _answer được tối ưu hóa và được đặt sau khi ghi vào _complete (Barrier 1) và chúng ta cần phải đảm bảo rằng _answer là không được lưu trữ (Rào cản 4). Tôi cũng nghĩ rằng tôi hiểu tại sao Barrier 3 là cần thiết: nếu A chạy cho đến khi chỉ sau khi viết _complete = true, B vẫn cần phải làm mới _complete để đọc đúng giá trị.
Tôi không hiểu tại sao chúng ta cần Barrier 2! Một phần của tôi nói rằng đó là bởi vì có lẽ Chủ đề 2 (chạy B) đã chạy đến (nhưng không bao gồm) nếu (_complete) và vì vậy chúng tôi cần đảm bảo rằng _complete được làm mới.
Tuy nhiên, tôi không thấy điều này sẽ hữu ích như thế nào. Không phải vẫn có thể là _complete sẽ được đặt thành true trong A nhưng phương pháp B sẽ thấy phiên bản được lưu trong bộ nhớ cache (false) là _complete? Tức là, nếu Thread 2 chạy phương thức B cho đến sau MemoryBarrier đầu tiên và sau đó Thread 1 chạy phương thức A cho đến _complete = true nhưng không tiếp tục, và sau đó Thread 1 tiếp tục và thử nghiệm nếu (_complete) - có thể nếu không dẫn đến false?
Tại sao mọi người sử dụng tính năng này trên 'biến động'? – ChaosPandion
@Chaos: CLR qua C# book (Richter) có một lời giải thích tuyệt vời - IIRC nó 'dễ bay hơi' có nghĩa là tất cả các truy cập vào var được coi là dễ bay hơi và thực thi các rào cản bộ nhớ đầy đủ theo cả hai hướng. Đó là cách thường xuyên hơn perf hit hơn cần thiết nếu bạn thay vì chỉ cần một đọc hoặc viết một rào cản và chỉ trong truy cập cụ thể. –
@Chaos: không thực sự là điểm, nhưng một lý do là dễ bay hơi có những quirks riêng của nó liên quan đến tối ưu hóa trình biên dịch có thể dẫn đến bế tắc, xem http://www.bluebytesoftware.com/blog/2009/02/24/TheMagicalDuelingDeadlockingSpinLocks .aspx – hackerhasid