2014-12-06 12 views
11

Trên kiến ​​trúc x86, các cửa hàng đến cùng một vị trí bộ nhớ có tổng số thứ tự, ví dụ: xem this video. Các bảo đảm trong mô hình bộ nhớ C++ 11 là gì?Hai thư giãn sẽ được ghi vào cùng một vị trí trong các luồng khác nhau luôn luôn được xem theo cùng thứ tự bởi các luồng khác?

Chính xác hơn, trong

-- Initially -- 
std::atomic<int> x{0}; 

-- Thread 1 -- 
x.store(1, std::memory_order_release); 

-- Thread 2 -- 
x.store(2, std::memory_order_release); 

-- Thread 3 -- 
int r1 = x.load(std::memory_order_acquire); 
int r2 = x.load(std::memory_order_acquire); 

-- Thread 4 -- 
int r3 = x.load(std::memory_order_acquire); 
int r4 = x.load(std::memory_order_acquire); 

sẽ kết quả r1==1, r2==2, r3==2, r4==1 được phép (trên một số kiến ​​trúc khác so với x86)? Nếu tôi thay thế tất cả memory_order bằng cách std::memory_order_relaxed thì sao?

Trả lời

7

Không, kết quả như vậy không được phép. §1.10 [intro.multithread]/p8, 18 (trích dẫn N3936/C++ 14; cùng văn bản được tìm thấy trong đoạn 6 và 16 cho N3337/C++ 11):

8 Mọi sửa đổi đối với đặc biệt là đối tượng nguyên tử M xảy ra ở một số tổng thứ tự đặc biệt, được gọi là trật tự sửa đổi của M.

18 Nếu một giá trị tính toán A của một đối tượng nguyên tử M xảy ra trước khi một tính toán B giá trị của M, và A mất nó giá trị từ một tác dụng phụ X trên M, thì giá trị được tính bằng B sẽ là giá trị được lưu trữ bởi X hoặc giá trị được lưu trữ bởi một tác dụng phụ Y trên M, trong đó Y foll ows X trong thứ tự sửa đổi của M. [Lưu ý: Yêu cầu này được gọi là kết hợp đọc đọc. - lưu ý cuối]

Trong mã của bạn có hai tác dụng phụ, và bởi p8 chúng xuất hiện theo một số thứ tự cụ thể. Trong Chủ đề 3, tính toán giá trị để tính giá trị được lưu trữ trong r1 xảy ra trước số r2, vì vậy hãy cho r1 == 1r2 == 2 chúng tôi biết rằng cửa hàng được thực hiện theo Chủ đề 1 trước cửa hàng được thực hiện bởi Chủ đề 2 theo thứ tự sửa đổi x. Trong trường hợp đó, Thread 4 không thể quan sát r3 == 2, r4 == 1 mà không cần chạy afoul của p18. Đây là bất kể số memory_order được sử dụng.

Có một lưu ý trong p21 (P19 trong N3337) có liên quan:

[Note: Bốn trước yêu cầu gắn kết có hiệu quả disallow biên dịch sắp xếp lại các hoạt động nguyên tử vào một đối tượng duy nhất, thậm chí nếu cả hai hoạt động được tải thoải mái. Điều này có hiệu quả đảm bảo tính bảo mật kết hợp bộ nhớ cache được cung cấp bởi hầu hết phần cứng có sẵn cho hoạt động nguyên tử C++ . - cuối note]

+0

Bạn có thể giúp tôi hiểu p18 không? Từ đồng nghĩa 'tính toán giá trị' có từ đồng nghĩa với tải nguyên tử và' tác dụng phụ' có lưu trữ thành nguyên tử không? –

+0

@ TobiasBrüll Tải là một tính toán giá trị; cửa hàng là một tác dụng phụ. –

+0

Loại tính toán giá trị nào khác tồn tại? Và loại tác dụng phụ nào khác? –

4

mỗi C++ 11 [intro.multithread]/6: "Tất cả những thay đổi đến một đối tượng nguyên tử đặc biệt M xảy ra ở một số tổng thứ tự đặc biệt, được gọi là trình tự sửa đổi M" Do đó, số lần đọc của một đối tượng nguyên tử theo một chuỗi cụ thể sẽ không bao giờ thấy các giá trị "cũ" hơn so với các chủ đề đã được quan sát. Lưu ý rằng không có đề cập đến thứ tự bộ nhớ ở đây, vì vậy thuộc tính này giữ đúng cho tất cả chúng - seq_cst đến relaxed.

Trong ví dụ được đưa ra trong OP, thứ tự sửa đổi của x có thể là (0,1,2) hoặc (0,2,1). Một chủ đề đã quan sát một giá trị đã cho trong thứ tự sửa đổi đó sau đó không thể quan sát một giá trị trước đó. Kết quả r1==1, r2==2 ngụ ý rằng thứ tự sửa đổi của x(0,1,2), nhưng r3==2, r4==1 ngụ ý rằng nó là (0,2,1), một mâu thuẫn. Vì vậy, kết quả là không thể thực hiện trên một thực hiện phù hợp với C++ 11.

Các vấn đề liên quan