2011-08-16 25 views
7

Tôi có một phụ huynh và một sợi công nhân chia sẻ một cờ bool và một std :: vector. Cha mẹ chỉ đọc (tức là, đọc bool hoặc gọi my_vector.empty()); công nhân chỉ viết.Một người đọc. Một nhà văn. Một số câu hỏi chung về mutexes và nguyên tử-xây dựng

Câu hỏi của tôi:

  • Tôi có cần phải mutex bảo vệ lá cờ bool?

  • Tôi có thể nói rằng tất cả các thao tác đọc/ghi bool vốn là các hoạt động nguyên tử không? Nếu bạn nói Có hoặc Không, bạn đã lấy thông tin từ đâu?

  • Gần đây tôi đã nghe nói về GCC Atomic-builtin. Tôi có thể sử dụng chúng để làm cho cờ của tôi đọc/ghi nguyên tử mà không cần phải sử dụng mutexes không? Sự khác biệt là gì? Tôi hiểu các nội trang Atomic sôi xuống mã máy, nhưng ngay cả các mutex cũng có thể làm hỏng các chỉ lệnh rào cản bộ nhớ của CPU phải không? Tại sao mọi người gọi mutex là cấu trúc "cấp độ hệ điều hành"?

  • Tôi có cần phải bảo vệ mutex std :: vector của mình không? Hãy nhớ lại rằng chuỗi công nhân điền vào vectơ này, trong khi cha mẹ chỉ gọi rỗng() trên nó (tức là chỉ đọc nó)

  • Tôi không tin rằng bảo vệ mutex là cần thiết cho bool hoặc vector. Tôi hợp lý hóa như sau, "Ok, nếu tôi đọc bộ nhớ chia sẻ ngay trước khi nó được cập nhật .. thats vẫn còn tốt, tôi sẽ nhận được giá trị cập nhật trong thời gian tới. Quan trọng hơn, tôi không thấy lý do tại sao các nhà văn nên bị chặn trong khi đọc là đọc, bởi vì sau đó, người đọc chỉ đọc! "

Nếu ai đó có thể chỉ cho tôi đúng hướng, điều đó thật tuyệt vời. Tôi đang sử dụng GCC 4.3 và Intel x86 32 bit. Cảm ơn rất nhiều!

Trả lời

13

Tôi có cần phải bảo vệ mutex cờ bool không?

Không nhất thiết phải có chỉ dẫn nguyên tử. Bởi atomic instruction Tôi có nghĩa là một chức năng biên dịch nội tại a) ngăn cản trình biên dịch sắp xếp lại/tối ưu hóa và b) kết quả trong đọc/ghi nguyên tử và c) phát hành hàng rào bộ nhớ thích hợp để đảm bảo khả năng hiển thị giữa các CPU (không cần thiết cho CPU x86 hiện tại sử dụng MESI cache coherency protocol). Tương tự như gcc atomic builtins.

Tôi có thể nói rằng tất cả các hoạt động đọc/ghi bool vốn là hoạt động nguyên tử không? Nếu bạn nói Có hoặc Không, bạn đã lấy thông tin từ đâu?

Phụ thuộc vào CPU. Đối với CPU Intel - có. Xem Intel® 64 and IA-32 Architectures Software Developer's Manuals.

Gần đây tôi đã nghe về GCC Atomic-builtin.Tôi có thể sử dụng chúng để làm cho cờ của tôi đọc/ghi nguyên tử mà không cần phải sử dụng mutexes không? Sự khác biệt là gì? Tôi hiểu các nội trang Atomic sôi xuống mã máy, nhưng ngay cả các mutex cũng có thể làm hỏng các chỉ lệnh rào cản bộ nhớ của CPU phải không? Tại sao mọi người gọi mutex là cấu trúc "cấp độ hệ điều hành"?

Sự khác biệt giữa nguyên tử và mutexes là sau này có thể đặt luồng chờ đợi cho đến khi phát hành mutex. Với nguyên tử bạn chỉ có thể bận rộn quay.

Tôi có cần phải bảo vệ mutex std :: vector không? Nhớ lại rằng chuỗi công nhân điền vào vectơ này, trong khi cha mẹ chỉ gọi rỗng() trên nó (tức là chỉ đọc nó)

Bạn làm.

Tôi không tin rằng bảo vệ mutex là cần thiết đối với bool hoặc vectơ. Tôi hợp lý hóa như sau, "Ok, nếu tôi đọc bộ nhớ chia sẻ ngay trước khi nó được cập nhật .. thats vẫn còn tốt, tôi sẽ nhận được giá trị cập nhật trong thời gian tới. Quan trọng hơn, tôi không thấy lý do tại sao các nhà văn nên bị chặn trong khi đọc là đọc, bởi vì sau đó, người đọc chỉ đọc! "

Tùy thuộc vào việc thực hiện, vector.empty() có thể bao gồm đọc hai bộ đệm bắt đầu/con trỏ cuối và trừ hoặc so sánh chúng, vì vậy có một cơ hội mà bạn đọc một phiên bản mới của một con trỏ và một phiên bản cũ của nhau mà không có một mutex. Hành vi đáng ngạc nhiên có thể xảy ra.

+1

Liên quan đến 'bool', anh ấy chắc chắn cần điều gì đó để đảm bảo rằng quyền truy cập thực sự diễn ra khi anh ấy nghĩ. Nếu anh ta có một trình biên dịch hỗ trợ 'std :: atomic <>', thì điều đó là đủ; nếu không, anh ta cần hoặc một số loại cơ chế đồng bộ hóa, hoặc một số phương tiện khác để đảm bảo rằng các hàng rào cần thiết, vv có mặt. –

+0

Cũng lưu ý rằng 'std :: vector' có thể di chuyển nội dung của nó từ dưới chân của bạn khi nó cần phải phân bổ lại cho bộ đệm lớn hơn. Tại thời điểm này người tiêu dùng có thể đọc bộ nhớ 'xóa'-ed. –

+0

@Maxim: Tôi cần làm rõ, theo các hoạt động hướng dẫn sử dụng của Intel trên bools vốn đã nguyên tử, nhưng bạn nói trong câu trả lời đầu tiên của bạn rằng "một lệnh nguyên tử sẽ làm". Bạn có mâu thuẫn không? Hoặc, bạn đang nói rằng tôi nên được ở bên an toàn và sử dụng một builtin nguyên tử incase mã của tôi bao giờ chạy trên một hệ thống không phải của Intel? – Kostolma

2

Đáp:

  1. Bạn sẽ cần phải bảo vệ bool (hoặc bất kỳ biến khác cho rằng vấn đề) có khả năng được vận hành trên bởi hai hoặc nhiều chủ đề cùng một lúc. Bạn có thể làm điều này với một mutex hoặc bằng cách hoạt động trên bool nguyên tử.
  2. Bool lần đọc và bool viết có thể là hoạt động nguyên tử, nhưng hai hoạt động tuần tự chắc chắn không phải (ví dụ: đọc và sau đó viết). Thêm về điều này sau.
  3. Nội trang nguyên tử cung cấp giải pháp cho vấn đề ở trên: khả năng đọc và viết biến trong bước không thể bị gián đoạn bởi chuỗi khác. Điều này làm cho hoạt động nguyên tử.
  4. Nếu bạn đang sử dụng cờ bool làm 'mutex' (nghĩa là chỉ có chuỗi đặt cờ bool là true mới được phép sửa đổi vectơ) thì bạn đã OK. Việc loại trừ lẫn nhau được quản lý bởi boolean, và miễn là bạn đang sửa đổi bool bằng cách sử dụng các hoạt động nguyên tử, bạn nên được tất cả các thiết lập.
  5. Để trả lời câu này, hãy để tôi sử dụng một ví dụ:

 

bool    flag(false); 
std::vector<char> my_vector; 

while (true) 
{ 
    if (flag == false) // check to see if the mutex is owned 
    { 
     flag = true; // obtain ownership of the flag (the mutex) 

     // manipulate the vector 

     flag = false; // release ownership of the flag 
    } 
} 

Trong đoạn mã trên trong một môi trường đa luồng nó có thể cho các chủ đề được preempted giữa tuyên bố if (các đọc) và bài tập (ghi), có nghĩa là có thể cho hai chủ đề (hoặc nhiều hơn) với loại mã này cho cả hai "sở hữu" mutex (và quyền đối với vectơ) cùng một lúc. Đây là lý do tại sao các hoạt động nguyên tử là rất quan trọng: chúng đảm bảo rằng trong kịch bản trên, cờ sẽ chỉ được đặt bởi một luồng tại một thời điểm, do đó đảm bảo vectơ sẽ chỉ được thao tác bởi một luồng tại một thời điểm.

Lưu ý rằng việc đặt cờ lại thành không cần phải là thao tác nguyên tử vì bạn là cá thể duy nhất có quyền sửa đổi nó.

Một thô (đọc: chưa được kiểm tra) giải pháp có thể giống như thế:

bool    flag(false); 
std::vector<char> my_vector; 

while (true) 
{ 
    // check to see if the mutex is owned and obtain ownership if possible 
    if (__sync_bool_compare_and_swap(&flag, false, true)) 
    { 
     // manipulate the vector 

     flag = false; // release ownership of the flag 
    } 
} 

Các tài liệu cho xây dựng trong nguyên tử lần đọc:

Phiên bản “bool” trả về true nếu so sánh là thành công và newval được viết.

Điều đó có nghĩa là thao tác sẽ kiểm tra xem cờ có sai không và nếu nó được đặt giá trị thành true. Nếu giá trị là false true được trả về, ngược lại sai. Tất cả điều này xảy ra trong một bước nguyên tử, do đó, nó được đảm bảo không được preempted bởi thread khác.

0

Tôi không có chuyên môn để trả lời toàn bộ câu hỏi của bạn nhưng viên đạn cuối cùng của bạn không chính xác trong trường hợp lần đọc không phải là nguyên tử theo mặc định.

Công tắc ngữ cảnh có thể xảy ra ở bất kỳ đâu, người đọc có thể chuyển ngữ cảnh sang một phần đọc, người viết có thể chuyển sang và viết toàn bộ, sau đó người đọc sẽ đọc xong. Người đọc sẽ không thấy giá trị đầu tiên, cũng không phải giá trị thứ hai, nhưng có khả năng một số giá trị trung gian cực kỳ không chính xác.

2

Từ quan điểm tiêu chuẩn C++ 11, bạn phải bảo vệ bool bằng mutex, hoặc cách khác sử dụng std::atomic<bool>. Ngay cả khi bạn chắc chắn rằng bool của bạn được đọc và ghi vào anyways nguyên tử, vẫn có khả năng trình biên dịch có thể tối ưu hóa việc truy cập vào nó bởi vì nó không biết về các luồng khác có khả năng truy cập nó.

Nếu vì lý do nào đó bạn hoàn toàn cần chút hiệu suất mới nhất của nền tảng, hãy xem "Hướng dẫn dành cho nhà phát triển phần mềm kiến ​​trúc Intel 64 và IA-32", nó sẽ cho bạn biết mọi thứ hoạt động như thế nào trên mui xe của bạn. Nhưng tất nhiên, điều này sẽ làm cho chương trình của bạn không thể di chuyển được.

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