2013-08-08 38 views
7

Tôi có một biến số int foo được truy cập từ hai luồng. Giả sử tôi không có vấn đề về chủng tộc (truy cập được bảo vệ bởi một mutex, tất cả các hoạt động đều là nguyên tử, hoặc bất kỳ phương pháp nào khác để bảo vệ khỏi điều kiện chủng tộc), vẫn còn vấn đề "đăng ký bộ nhớ đệm" (vì thiếu tên tốt hơn) , nơi trình biên dịch có thể giả định rằng nếu biến được đọc hai lần mà không được viết ở giữa, nó là giá trị như nhau, và như vậy có thể "tối ưu hóa" mọi thứ đi như:`volatile` để đồng bộ biến giữa các chủ đề

while(foo) { // <-may be optimized to if(foo) while(1) 
    do-something-that-doesn't-involve-foo; 
} 

hoặc

if(foo) // becomes something like (my assembly is very rusty): mov ebx, [foo]; cmp ebx, 0; jz label; 
    do-something-that-doesn't-involve-foo; 
do-something-else-that-doesn't-involve-foo; 
if(foo) // <-may be optimized to jz label2; 
    do-something; 

không đánh dấu foovolatile giải quyết vấn đề này? Các thay đổi từ một luồng có được đảm bảo để đạt được luồng khác không?

Nếu không, còn cách nào khác để thực hiện việc này? Tôi cần một giải pháp cho Linux/Windows (có thể là các giải pháp riêng biệt), không có C++ 11.

+0

Tôi nhớ nhìn thấy một trích dẫn từ tiêu chuẩn nói rằng bạn không phải sử dụng dễ bay hơi cho các chủ đề nữa, trong C++, tôi sẽ cố gắng tìm nó – aaronman

+3

http: // stackoverflow.com/questions/4557979/khi-to-sử dụng-dễ bay hơi-với-đa luồng –

+1

Vấn đề ở đây là "Giả sử tôi không có vấn đề chủng tộc-điều kiện". Đó là một giả định ** ENORMOUS **. –

Trả lời

11

Điều bạn cần là rào cản bộ nhớ.

MemoryBarrier(); 

hoặc

__sync_synchronize(); 

Edit: Tôi đã in đậm những phần thú vị và đây là link đến bài viết wiki (http://en.wikipedia.org/wiki/Memory_barrier#cite_note-1) và tài liệu tham khảo liên quan (http://www.rdrop.com/users/paulmck/scalability/paper/whymb.2010.07.23a.pdf)

Dưới đây là câu trả lời cho Câu hỏi khác của bạn (từ wikipedia): Trong C và C++, từ khóa dễ bay hơi được dự định để cho phép các chương trình C và C++ truy cập trực tiếp vào I/O được ánh xạ bộ nhớ. I/O được ánh xạ bộ nhớ thường yêu cầu các lần đọc và ghi được chỉ định trong mã nguồn xảy ra theo thứ tự chính xác được chỉ định không có thiếu sót. Việc thiếu sót hoặc sắp xếp lại các lần đọc và ghi bởi trình biên dịch sẽ phá vỡ sự liên lạc giữa chương trình và thiết bị được truy cập bởi bộ nhớ I/O được ánh xạ. Trình biên dịch C hoặc C++ không thể sắp xếp lại các lần đọc và ghi vào các vị trí bộ nhớ dễ bay hơi, cũng như không thể bỏ qua việc đọc hoặc ghi vào một vị trí bộ nhớ dễ bay hơi. Từ khóa dễ bay hơi không đảm bảo rào cản bộ nhớ để thực thi tính nhất quán của bộ nhớ cache. Do đó việc sử dụng "không ổn định" không thôi thì không đủ để sử dụng một biến để giao tiếp giữa các chủ đề trên tất cả các hệ thống và xử lý [1]

Kiểm tra này ra, nó cung cấp những giải thích rất lớn về đề tài này: http://channel9.msdn.com/Shows/Going+Deep/Cpp-and-Beyond-2012-Herb-Sutter-atomic-Weapons-1-of-2 http://channel9.msdn.com/Shows/Going+Deep/Cpp-and-Beyond-2012-Herb-Sutter-atomic-Weapons-2-of-2

9

Nếu quyền truy cập được bảo vệ bằng một mutex, bạn không có bất kỳ vấn đề nào cần phải lo lắng. Từ khóa volatile là vô ích ở đây. Một mutex là một hàng rào bộ nhớ đầy đủ và do đó không có đối tượng nào có địa chỉ có thể được hiển thị bên ngoài có thể được lưu trữ qua khóa mutex hoặc mở khóa cuộc gọi.

+0

Đúng. Mutex chăm sóc tính nhất quán của bộ nhớ cache. – MasterPlanMan

+0

Để rõ ràng: theo bộ nhớ cache, tôi có nghĩa là không chỉ bộ nhớ cache cấp máy, mà còn là bộ nhớ cache của trình biên dịch của các giá trị trong sổ đăng ký. –

1

Từ khóa volatile ban đầu được giới thiệu để cho biết giá trị có thể được phần cứng thay đổi. Điều này xảy ra khi thiết bị phần cứng có bộ nhớ được ánh xạ bộ nhớ hoặc bộ nhớ đệm. Cách tiếp cận đúng là sử dụng nó chỉ cho mục đích này.

Tất cả cấu trúc ngôn ngữ đồng bộ hóa hiện đại và thư viện đồng bộ hóa không sử dụng từ khóa này. Các lập trình viên ứng dụng nên làm điều tương tự.

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