2013-01-31 30 views
23

Giả sử chúng ta có hai chủ đề, một là đọc một bool trong một vòng lặp và một người khác có thể chuyển đổi nó vào những thời điểm nhất định. Cá nhân tôi nghĩ rằng điều này nên được nguyên tử bởi vì sizeof(bool) trong C + + là 1 byte và bạn không đọc/ghi byte một phần nhưng tôi muốn được 100% chắc chắn.Thao tác đọc/ghi bool không phải là nguyên tử trên x86?

Vậy có hay không?

EDIT:

Ngoài ra để tham khảo trong tương lai, không giống nhau áp dụng cho int?

+0

Không phải bất kỳ thứ gì nhỏ hơn kích thước của kiến ​​trúc cơ bản cả * nguyên tử * và cũng * kém hiệu quả * hơn có thể? –

+0

http://stackoverflow.com/questions/8037289/is-mutex-required-for-1-byte-shared-memory cho thấy nó không phải nguyên tử. –

+0

http://stackoverflow.com/questions/8517969/is-this-the-correct-way-to-atomically-read-and-write-a-bool cho thấy đó là nguyên tử "trong hầu hết các máy". –

Trả lời

14

Tất cả phụ thuộc vào ý nghĩa của từ "nguyên tử". Bạn có nghĩa là "giá trị cuối cùng sẽ được cập nhật một lần" (có, trên x86 chắc chắn được đảm bảo cho giá trị byte - và bất kỳ giá trị được căn chỉnh chính xác nào tối thiểu là 64 bit) hoặc "nếu tôi đặt giá trị này đúng (hoặc sai), không có chủ đề nào khác sẽ đọc một giá trị khác sau khi tôi đã đặt nó "(điều đó không hoàn toàn chắc chắn - bạn cần tiền tố" khóa "để đảm bảo).

+0

"nếu tôi đặt giá trị này thành true (hoặc false), không có chuỗi nào khác sẽ đọc một giá trị khác sau khi tôi đã đặt nó". Tôi nghĩ câu hỏi khá rõ ràng. Cách giải thích thứ hai này không liên quan gì tới nguyên tử. – jberryman

+2

@jberryman: Vấn đề đi kèm với bộ đệm cũng như trình biên dịch tối ưu hóa việc đọc bộ nhớ. 'B = false;' trong một số luồng, không đảm bảo rằng tất cả các luồng khác, trong trường hợp tiếp theo của 'if (b) ...', sẽ nhận biết rằng 'b' là sai. Điều này yêu cầu trình biên dịch không tối ưu hóa quyền truy cập vào 'b' vào' tmp = b; ... if (tmp) ... '[trong đó' tmp' là một thanh ghi]. Tùy thuộc vào mã bên trong luồng, có các tình huống khi trình biên dịch S do làm điều này. –

6

x86 chỉ đảm bảo đọc và viết từ được căn chỉnh từ. Nó không đảm bảo bất kỳ hoạt động nào khác, trừ khi nguyên tử rõ ràng. Ngoài ra, tất nhiên, bạn phải thuyết phục trình biên dịch của mình thực sự phát hành các lần đọc và viết có liên quan ngay từ đầu.

52

Có ba vấn đề riêng biệt mà các loại "nguyên tử" trong C++ 11 địa chỉ:

  1. rách: a đọc hoặc ghi liên quan đến nhiều chu kỳ bus, và một công tắc đề xảy ra ở giữa hoạt động ; điều này có thể tạo ra các giá trị không chính xác.

  2. kết hợp bộ nhớ cache: ghi từ một luồng cập nhật bộ nhớ cache của bộ xử lý nhưng không cập nhật bộ nhớ chung; đọc từ một luồng khác đọc bộ nhớ toàn cục và không thấy giá trị được cập nhật trong bộ nhớ cache của bộ xử lý khác.

  3. tối ưu hóa trình biên dịch: trình biên dịch xáo trộn thứ tự đọc và ghi theo giả định rằng các giá trị không được truy cập từ một chuỗi khác, dẫn đến hỗn loạn.

Sử dụng std::atomic<bool> đảm bảo rằng cả ba vấn đề này đều được quản lý chính xác. Không sử dụng std::atomic<bool> để bạn đoán, với, tốt nhất, không phải mã di động.

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