Tôi có đoạn mã sau C++ 2011:C++ memory_order với hàng rào và aquire/phát hành
std::atomic<bool> x, y;
std::atomic<int> z;
void f() {
x.store(true, std::memory_order_relaxed);
std::atomic_thread_fence(std::memory_order_release);
y.store(true, std::memory_order_relaxed);
}
void g() {
while (!y.load(std::memory_order_relaxed)) {}
std::atomic_thread_fence(std::memory_order_acquire);
if (x.load(std::memory_order_relaxed)) ++z;
}
int main() {
x = false;
y = false;
z = 0;
std::thread t1(f);
std::thread t2(g);
t1.join();
t2.join();
assert(z.load() !=0);
return 0;
}
Tại lớp kiến trúc máy tính của tôi, chúng tôi đã được cho biết rằng khẳng định trong mã này luôn trở thành hiện thực. Nhưng sau khi xem xét nó thouroughly bây giờ, tôi không thể thực sự hiểu tại sao nó như vậy.
Đối với những gì tôi biết:
- Một hàng rào với 'memory_order_release' sẽ không cho phép các cửa hàng trước để được thực thi sau khi nó
- Một hàng rào với 'memory_order_acquire' sẽ không cho phép điều đó bất kỳ tải đến sau khi nó được thực thi trước nó.
Nếu hiểu biết của tôi là chính xác, tại sao chuỗi hành động sau đây không xảy ra?
- Bên t1,
y.store(true, std::memory_order_relaxed);
được gọi - t2 chạy hoàn toàn, và sẽ thấy một 'false' khi tải 'x', do đó không tăng z trong một đơn vị
- t1 kết thúc thực hiện
- Trong chủ đề chính, khẳng định không thành công vì z.load() trả về 0
Tôi nghĩ điều này tuân thủ các quy tắc 'có được' - 'phát hành', nhưng, ví dụ câu trả lời hay nhất trong câu hỏi này: Understanding c++11 memory fences. simi lar cho trường hợp của tôi, nó gợi ý rằng một cái gì đó giống như bước 1 trong chuỗi hành động của tôi không thể xảy ra trước khi 'memory_order_release', nhưng không nhận được vào chi tiết vì lý do đằng sau nó.
tôi là terribly bối rối về điều này, và sẽ rất vui mừng nếu có ai có thể làm sáng tỏ về nó :)
+1 để biết thông tin thú vị. Nhưng câu hỏi: Bạn có nói rằng trên kiến trúc không liên kết với bộ nhớ cache, ngay cả hàng rào bộ nhớ 'memory_order_release' không đủ để đảm bảo bộ nhớ cache của các bộ vi xử lý khác được cập nhật? – jogojapan
Không, tôi nói rằng 'sử dụng memory_order_release' sẽ đảm bảo bộ nhớ cache-mạch lạc. Nhưng tôi phải xin lỗi, tôi đã đọc sai mã của bạn - tôi không thấy điều này sẽ thất bại như thế nào. Nếu y đúng với t2, thì x sẽ đúng trong t2. Vì vậy, giả sử vòng lặp 't2' cuối cùng kết thúc, thì' z' sẽ được tăng lên. Xin lỗi vì điều đó. –
Tôi sẽ cập nhật câu trả lời. Nhưng nhớ rằng hai "tham gia" đảm bảo rằng cả hai chủ đề được hoàn thành trước khi chính được xác nhận. –