2010-07-09 39 views
37

giả sử tôi có đoạn mã sau:Là một truy vấn LINQ để ConcurrentDictionary giá trị threadsafe?

ConcurrentDictionary<long, long> myDict= new ConcurrentDictionary<long, long>(); 

Thông thường mỗi truy cập bởi quan trọng là threadsafe, nhưng cũng là LINQ truy vấn threadsafe sau đây? tôi đã không tìm thấy bất cứ điều gì trong tài liệu: http://msdn.microsoft.com/en-us/library/dd287226.aspx

if myDict.Values.Any(x => !x.HasPaid)) 
{ 
    return false 
} 

Trả lời

37

Correction ... Tôi không chắc chắn khi bạn đang truy cập vào giá trị tài sản. Đó là luồng an toàn khi sử dụng LINQ trên chính đối tượng đó.


LINQ sẽ sử dụng phương pháp GetEnumerator để thay đổi các mục.

Trực tiếp từ MSDN

Các điều tra viên trở về từ điển là an toàn để sử dụng đồng thời với đọc và viết vào từ điển, tuy nhiên nó không đại diện cho một ảnh chụp khoảnh khắc-in-time của từ điển. Nội dung tiếp xúc thông qua các điều tra viên có thể chứa những thay đổi được thực hiện vào từ điển sau GetEnumerator được gọi

if myDict.Any(x => !x.Value.HasPaid)) 
{ 
    return false 
} 
33

Như đã đề cập, ConcurrentDictionary.GetEnumerator() không đại diện cho một ảnh chụp khoảnh khắc-in-time của từ điển. Tuy nhiên, ConcurrentDictionary.Values ​​không tạo ra ảnh chụp nhanh theo thời gian.

Vì vậy sau đây là không tương đương:

myDict.Any(x => !x.Value.HasPaid) 
myDict.Values.Any(x => !x.HasPaid) 
+0

Thú vị, bạn có một nguồn cho điều này? Tài liệu của .Values ​​không đề cập cụ thể nó là một ảnh chụp nhanh: http://msdn.microsoft.com/en-us/library/dd381929.aspx –

+7

Tài liệu không rõ ràng ngoại trừ việc nó trả về một bộ sưu tập so với một số đếm. Nhưng hãy xem mã nguồn: Giá trị getter gọi GetValues ​​() để lấy khóa, cấu trúc và điền vào một danh sách mới và giải phóng khóa. – Kevin

+1

Ah cảm ơn bạn, tôi không tự xem mã nguồn. Tất nhiên nếu đây không phải là tài liệu này là một chi tiết thực hiện có thể thay đổi, nhưng vẫn còn thú vị để biết. –

9

Các tài liệu của ConcurrentDictionary khẳng định:

Tất cả các thành viên cộng đồng và bảo vệ của ConcurrentDictionary là thread-safe và có thể được sử dụng đồng thời từ nhiều chủ đề.

Vì thuộc tính .Values ​​là một thực thi được quy định bởi giao diện IColletion, nó là công khai và do đó luồng an toàn.

+3

Đó là chủ đề an toàn, nhưng mua lại một khóa dẫn đến deadlocks có thể. Tương tự với Count, Keys và IsEmpty: http://geekswithblogs.net/simonc/archive/2012/02/22/inside-the-concurrent-collections-concurrentdictionary.aspx – DuneCat

+5

Chúng có thể làm giảm sự tương tranh của bạn, nhưng các khóa bên trong không thể gây Deadlock. Deadlock yêu cầu các hoạt động chờ đợi lẫn nhau và không có thứ nào được thực hiện bên trong các khóa có thể gọi lại cho mã của bạn mà có thể cố gắng thực hiện một thứ gì đó cũng cần khóa. – me22

+0

Đúng! Tôi đứng sửa. Tôi vẫn đánh giá cao đề nghị các mục blog liên kết để tham khảo trên internals của các bộ sưu tập đồng thời, mặc dù. – DuneCat

4

Tất cả các câu trả lời cho đến nay là tuyệt vời và hữu ích, nhưng tôi nghĩ rằng các liên kết mà DuneCat chỉ ra trong một trong những nhận xét cũng nhấn mạnh:

http://geekswithblogs.net/simonc/archive/2012/02/22/inside-the-concurrent-collections-concurrentdictionary.aspx

Cụ .....

Lockless:

  • TryGetValue
  • GetEnumerator
  • Các indexer getter
  • containsKey

Đưa ra mỗi khóa (lockfull?):

  • Đếm
  • IsEmpty
  • Phím
  • Values ​​
  • CopyTo
  • ToArray
Các vấn đề liên quan