2016-07-12 16 views
9

Các tài liệu MSDN của System.Collections.Concurrent.ConcurrentDictionary nói:Thành viên của .NET ConcurrentDictionary nào an toàn chỉ?

Chủ đề An toàn

Tất cả các thành viên cộng đồng và bảo vệ của ConcurrentDictionary<TKey, TValue> là thread-safe và có thể được sử dụng đồng thời từ nhiều chủ đề. Tuy nhiên, thành viên được truy cập thông qua một trong các giao diện ConcurrentDictionary<TKey, TValue> thực hiện, bao gồm các phương pháp mở rộng, không được bảo đảm là an toàn chủ đề và có thể cần được đồng bộ hóa bởi người gọi.

(tôi nhấn mạnh)

Điều này có vẻ tự mâu thuẫn. "Tất cả các thành viên đều an toàn. Tuy nhiên, các thành viên [đôi khi] không an toàn."

Tôi hiểu rằng phương pháp mở rộng tất nhiên không được bảo đảm là chuỗi an toàn.

Nhưng ý nghĩa của chúng là "được truy cập thông qua một trong các giao diện"? Có phải TryGetValue (một thành viên của giao diện IDictionary<TKey, TValue>) có an toàn không?

Trả lời

4

Lưu ý phần tài liệu bao gồm explicit interface implementations. Ví dụ. lớp thực hiện IDictionary.Add. Phương pháp này là không phải là thành viên công khai hoặc được bảo vệ của lớp học, nhưng có thể truy cập được qua giao diện IDictionary. Đó là những thành viên như vậy mà không được đảm bảo để được thread an toàn.

+0

Bất kỳ ý tưởng nào tại sao lại như vậy? – Peter

+4

@Peter - tốt, cho một, có ít giá trị trong * cung cấp * bảo lãnh như vậy vì nếu bạn đang truy cập thông qua giao diện như vậy, có khả năng mã gọi có thể sử dụng bảo lãnh (vì các triển khai khác sẽ không cung cấp bảo lãnh như vậy). –

3

Có một phần cụ thể trong the documentation mà làm cho rõ ràng không phải mọi thứ là thread-safe trong ConcurrentDictionary<TKey, TValue>:

Tất cả các hoạt động này là nguyên tử và là thread-safe liên quan đến tất cả các hoạt động khác trên lớp ConcurrentDictionary<TKey, TValue> . Ngoại lệ duy nhất là các phương thức chấp nhận một đại biểu, nghĩa là, AddOrUpdateGetOrAdd. Để sửa đổi và ghi các hoạt động vào từ điển, ConcurrentDictionary<TKey, TValue> sử dụng khóa hạt mịn để đảm bảo an toàn luồng. (Các thao tác đọc trên từ điển được thực hiện một cách không có khóa.) Tuy nhiên, các đại biểu cho các phương thức này được gọi bên ngoài các khóa để tránh các vấn đề có thể phát sinh từ việc thực thi mã không xác định dưới một khóa. Do đó, mã được thực hiện bởi các đại biểu này không phụ thuộc vào nguyên tử của hoạt động.

Vì vậy, có một số loại trừ chung và một số tình huống cụ thể để ConcurrentDictionary<TKey, TValue>:

  • Các đại biểu về AddOrUpdateGetOrAdd không được gọi trong một vài thread-safe.
  • Các phương pháp hoặc thuộc tính được gọi trên triển khai giao diện rõ ràng không được đảm bảo an toàn theo luồng;
  • Các phương pháp mở rộng được gọi trên lớp không được đảm bảo an toàn theo chủ đề;
  • Tất cả các hoạt động khác trên các thành viên công cộng của lớp đều an toàn.
+2

Đó không phải là trích dẫn chuẩn "thông thường" - báo giá thông thường chỉ tham chiếu các thành viên tĩnh. Ở đây, nhiều đảm bảo hơn đang được cung cấp về các thành viên cá thể. (Tôi tin rằng báo giá này khá phổ biến trong 'System.Collections.Concurrent' tuy nhiên) –

+0

OK. Thậm chí không nhận ra điều đó. @Damien_The_Unbeliever. Sẽ loại bỏ phần đầu tiên vì nó không thực sự thêm quá nhiều. –

+0

Các "tất cả các hoạt động này" -section là dưới đây là một bảng của vài phương pháp bổ sung được cung cấp bởi ConcurrentDictionary, và chỉ có vẻ đề cập đến những người, không? – Peter

3

Do Explicit vs Implicit interface implementation.

Nếu bạn nhìn vào source code for ConcurrentDictionary<TKey, TValue> bạn có thể thấy rằng có một số phương pháp triển khai rõ ràng giao diện (như object IDictionary.this[object key]) mặc dù nội bộ gọi phiên bản an toàn của cùng một thao tác này có thể thay đổi trong tương lai.

Hãy coi đó là phân chia trách nhiệm: Nếu tôi (là một lớp) nhận được một cá thể là ConcurrentDictionary<TKey, TValue> Tôi biết rằng đó là trách nhiệm của cá thể đó để thực hiện các thao tác theo cách an toàn.

Tuy nhiên, nếu tôi (một lần nữa là một lớp) nhận một phiên bản IDictionary<TKey, TValue> thì tôi nên biết nếu có hoặc không nên là mối quan tâm về an toàn luồng. Nếu không có mối quan tâm như vậy, tôi chỉ sử dụng từ điển vì nó nếu yêu cầu yêu cầutrách nhiệm của tôi để thực hiện tất cả các thao tác theo cách an toàn.

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