2015-03-03 17 views
7

Tôi chỉ tự hỏi liệu một điều kiện chủng tộc xảy ra trong các mã dưới đây:Race Điều kiện trong Async/chờ đợi Mã

int readingFiles; 
async Task<string> ReadFile (string file) 
{  
    ++readingFiles; 

    var text = await Stream.ReadFileAsync(file); 

    --readingFiles; 

    return text; 
} 

Nếu phương pháp ReadFile được thực hiện bởi một thread bơi, readingFiles sẽ được truy cập bởi hai chủ đề khác nhau và biến readFiles không được bảo vệ bởi bất kỳ thành phần đồng bộ hóa nào.

Điều đó có nghĩa là bản cập nhật đầu tiên cho readingFiles sẽ không được hiển thị cho chuỗi khác đang thi hành "--readingFiles". Tuy nhiên, tôi đã không bao giờ thấy rằng readingFiles bằng -1 sau "--readingFiles". Tôi kiểm tra xem các thread tương tự thực hiện các hoạt động ++ và - bằng cách sử dụng Thread.CurrentThread. Trong hầu hết các trường hợp, nó không phải là cùng một luồng và tôi vẫn không thấy readFiles là -1.

Mặc dù có điều kiện chủng tộc và readingFiles không dễ bay hơi, tại sao tôi không thấy ảnh hưởng của điều kiện chủng tộc này?

+0

Chắc chắn toàn bộ điểm của cách thức không đồng bộ/đang chờ sử dụng ngữ cảnh đồng bộ hiện tại có nghĩa là * * là "thành ngữ đồng bộ hóa" thích hợp - bạn không thể thấy chúng. –

+0

Thay vì '--readingFiles', hãy thử điều này:' var temp = readingFiles; Ngủ (1000); readingFiles = temp - 1; ' – Dialecticus

+0

Bạn chỉ chạy một thể hiện của ReadFile, đúng không? – usr

Trả lời

0

Có một số điều có thể xảy ra tại đây.

Đối với một, loại tệp thực thi nào bạn đang chạy? Khi await cháy, nó sử dụng bối cảnh đồng bộ hóa hiện tại, do đó, mã chờ đợi của bạn có thể được serialized thành 1 thread UI.

Ngoài ra, vì không có bảo vệ bộ nhớ hàng rào/biến động xung quanh thay đổi, chủ đề của bạn có thể đọc giá trị indiviually cache (như đã đề cập bởi @ Spo1ler trong bài viết của ông)

Ngoài ra, các hồ bơi thread có thể được lựa chọn để chạy cả hai yêu cầu của bạn trên cùng một chuỗi (nó nằm trong quyền của mình để làm như vậy - bạn đang cho phép .net/windows quyết định thời điểm và cách phân bổ chủ đề)

Tóm lại, bạn thực sự cần bảo vệ quyền truy cập vào biến với đồng bộ hóa hoặc các hoạt động liên khóa.

9

Không có điều kiện chủng tộc nào ở đây. Thời gian chạy .NET sẽ chèn các rào cản bộ nhớ thích hợp.

Cũng xem các ý kiến ​​trên: http://blogs.msdn.com/b/pfxteam/archive/2012/04/12/async-await-faq.aspx

Vâng, TPL bao gồm các vật chắn thích hợp khi nhiệm vụ được xếp hàng đợi và vào lúc bắt đầu/kết thúc thực hiện nhiệm vụ do đó giá trị được một cách thích hợp làm nhìn thấy được.

+3

Không có điều kiện chủng tộc * khi bạn gọi phương thức này một lần *. Nếu bạn gọi nó nhiều lần song song (trên cùng một ví dụ), tất nhiên nó không an toàn. Chỉ cần ném mà ra khỏi đó. – Servy

+0

vì vậy chờ đợi tuyên bố là một loại rào cản bộ nhớ. –

+0

@TomK .: Có; nó sẽ chăm sóc các rào cản bộ nhớ cho bạn. Như Servy đã đề cập, tất nhiên bạn phải cẩn thận không truy cập dữ liệu được chia sẻ từ nhiều luồng * cùng một lúc *. –

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