Tôi có sai khi giả định rằng tải nguyên tử cũng hoạt động như một hàng rào bộ nhớ đảm bảo rằng tất cả các bài viết không nguyên tử sẽ trở nên hiển thị trước các chủ đề khác không?Hành vi sắp xếp bộ nhớ của std :: atomic :: load
Để minh họa:
volatile bool arm1 = false;
std::atomic_bool arm2 = false;
bool triggered = false;
thread1:
arm1 = true;
//std::std::atomic_thread_fence(std::memory_order_seq_cst); // this would do the trick
if (arm2.load())
triggered = true;
thread2:
arm2.store(true);
if (arm1)
triggered = true;
Tôi mong rằng sau khi thực hiện cả hai 'kích hoạt' sẽ thành sự thật. Xin vui lòng không đề nghị để làm cho arm1 nguyên tử, điểm là để khám phá những hành vi của nguyên tử :: tải.
Trong khi tôi phải thừa nhận tôi không hiểu đầy đủ các định nghĩa chính thức về ngữ nghĩa thư giãn khác nhau của memory order Tôi nghĩ rằng tuần tự phù hợp đặt hàng là khá đơn giản ở chỗ nó đảm bảo rằng "tổng trật tự duy nhất tồn tại trong đó tất cả các chủ đề quan sát tất cả các sửa đổi theo cùng một thứ tự. " Với tôi điều này ngụ ý rằng std :: atomic :: load với thứ tự bộ nhớ mặc định của std :: memory_order_seq_cst cũng sẽ hoạt động như một hàng rào bộ nhớ. Điều này được chứng thực thêm bằng tuyên bố sau trong "Thứ tự liên tục theo thứ tự":
Tổng số thứ tự tuần tự yêu cầu một lệnh CPU hàng rào bộ nhớ đầy đủ trên tất cả các hệ thống đa lõi. Tuy nhiên, ví dụ đơn giản của tôi dưới đây cho thấy đây không phải là trường hợp với MSVC 2013, gcc 4.9 (x86) và clang 3.5.1 (x86), trong đó tải nguyên tử chỉ đơn giản là chuyển thành lệnh tải.
#include <atomic>
std::atomic_long al;
#ifdef _WIN32
__declspec(noinline)
#else
__attribute__((noinline))
#endif
long load() {
return al.load(std::memory_order_seq_cst);
}
int main(int argc, char* argv[]) {
long r = load();
}
Với gcc này trông giống như:
load():
mov rax, QWORD PTR al[rip] ; <--- plain load here, no fence or xchg
ret
main:
call load()
xor eax, eax
ret
tôi sẽ bỏ qua các msvc và kêu vang mà cơ bản là giống hệt nhau. Bây giờ trên gcc cho ARM chúng ta có được những gì tôi mong đợi:
load():
dmb sy ; <---- data memory barrier here
movw r3, #:lower16:.LANCHOR0
movt r3, #:upper16:.LANCHOR0
ldr r0, [r3]
dmb sy ; <----- and here
bx lr
main:
push {r3, lr}
bl load()
movs r0, #0
pop {r3, pc}
Đây không phải là một câu hỏi học tập, nó kết quả trong một điều kiện chủng tộc tinh tế trong mã của chúng tôi mà gọi vào câu hỏi hiểu biết của tôi về hành vi của std :: nguyên tử.
[(Cửa hàng sẽ yêu cầu hàng rào.)] (Http://www.cl.cam.ac.uk/~pes20/cpp/cpp0xmappings.html) –
@tc sai khi nói rằng tải có seq_cst ngữ nghĩa trên x86. Nhưng bạn đúng rằng họ đủ mạnh .. để có ngữ nghĩa về thủy sản – Anton
Vấn đề không phải với các mô hình bộ nhớ của bộ xử lý khác nhau mà đúng hơn là với tiêu chuẩn C++ đảm bảo cho tải nguyên tử ::. Vui lòng xem bản chỉnh sửa hiện chứa ví dụ về các kỳ vọng (có thể không chính xác) của tôi. – Alf