2009-12-22 27 views
15

Tôi đang cố gắng để có được một cái nhìn tổng quan về lý thuyết an toàn chủ đề đằng sau các bộ sưu tập trong C#.Tại sao không có bộ sưu tập đồng thời trong C#?

Tại sao không có bộ sưu tập đồng thời nào có trong Java? (java docs). Một số bộ sưu tập xuất hiện chủ đề an toàn nhưng nó không phải là rõ ràng với tôi những gì vị trí là ví dụ đối với:

  • hoạt động hợp chất,
  • an toàn của việc sử dụng vòng lặp,
  • hoạt động ghi

Tôi không muốn phát minh lại bánh xe! (Tôi không phải là một guru đa luồng và chắc chắn không đánh giá thấp như thế nào khó này sẽ được anyway).

Tôi hy vọng cộng đồng có thể trợ giúp.

+0

Phản hồi tuyệt vời - Tôi sẽ để điều này 'không được trả lời' trong một thời gian ngắn để giữ nó trên radar. Nếu bất kỳ ai có thêm bất kỳ liên kết nào đến các bài viết về trạng thái trước hoặc sau .Net 4.0 về chủ đề này thì vui lòng bao gồm. Cảm ơn mọi người. – Andrew

Trả lời

28

NET đã có tương đối "thấp cấp" hỗ trợ đồng thời cho đến bây giờ - nhưng .NET 4.0 giới thiệu các namespace System.Collections.Concurrent trong đó có các bộ sưu tập khác nhau mà được an toàn và hữu ích.

Câu trả lời của Andrew hoàn toàn chính xác về cách xử lý các bộ sưu tập trước .NET 4.0 - và đối với hầu hết sử dụng Tôi chỉ khóa một cách thích hợp khi truy cập bộ sưu tập được chia sẻ "bình thường". Tuy nhiên, các bộ sưu tập đồng thời giúp dễ dàng sử dụng hàng đợi của nhà sản xuất/người tiêu dùng, v.v.

+0

+1 cảm ơn Jon. Tôi đoán theo cách đó .net không ru người ta thành một cảm giác sai lầm về sự bí mật. Tôi sẽ kiểm tra các goodies .Net 4.0. - Andrew – Andrew

+0

+1 Tốt, quên tất cả về điều đó :) –

19

C# cung cấp một số cách để làm việc với các bộ sưu tập trên nhiều luồng. Đối với một tốt write-up của những kỹ thuật này tôi sẽ khuyên bạn nên bắt đầu với Collections and Synchronization (Thread Safety):

Theo mặc định, bộ sưu tập các lớp học là thường không đề an toàn. Nhiều người đọc có thể đọc bộ sưu tập với sự tự tin ; tuy nhiên, bất kỳ sửa đổi nào cho bộ sưu tập sẽ tạo ra các kết quả không xác định cho tất cả các chuỗi truy cập bộ sưu tập, bao gồm cả trình đọc chủ đề.

lớp Collections có thể được thực hiện chủ đề an toàn sử dụng bất kỳ phương pháp sau đây:

  • Tạo một wrapper thread-safe sử dụng phương pháp đồng bộ, và truy cập bộ sưu tập độc quyền qua wrapper đó.
  • Nếu lớp học không có phương thức Đồng bộ, lấy từ lớp và triển khai phương thức Đồng bộ bằng thuộc tính SyncRoot.
  • Sử dụng cơ chế khóa, chẳng hạn như báo cáo khóa trong C# (SyncLock trong Visual Basic), trên thuộc tính SyncRoot khi truy cập bộ sưu tập .
+0

+1 đã nhanh! - trông giống như Collections.synchronizedList từ Java. Tôi sẽ kiểm tra liên kết đó. Cảm ơn – Andrew

+4

Và xem thêm tại đây: http://blogs.msdn.com/ericlippert/archive/2008/01/21/immutability-in-c-part-nine-academic-plus-my-avl-tree-implementation.aspx nơi Eric Lippert thảo luận về các bộ sưu tập bất biến ở độ sâu nào đó, đặc biệt liên quan đến việc truy cập đồng thời. –

+0

Cảm ơn Jeremy đã không đi qua blog này (bây giờ đã đăng ký) có một số tài liệu tuyệt vời dưới thẻ bất biến. – Andrew

6

Như Jon Skeet đã đề cập, hiện có các bộ sưu tập "an toàn chủ đề" trong không gian tên System.Collections.Concurrent trong .NET 4.

Một trong những lý do khiến không có bộ sưu tập đồng thời tồn tại (ít nhất là dự đoán của tôi) trước đây.NET Framework phiên bản là nó là rất khó để đảm bảo an toàn thread, ngay cả với một bộ sưu tập đồng thời.

(Đây không phải là hoàn toàn đúng như một số bộ sưu tập cung cấp một phương pháp đồng bộ để trả lại một bộ sưu tập chủ đề an toàn từ một bộ sưu tập an toàn phi thread vì vậy có một số bộ sưu tập chủ đề an toàn ...)

Ví dụ giả định một người có một từ điển an toàn chủ đề - nếu một người chỉ muốn chèn vào nếu Khóa không tồn tại thì trước tiên người ta sẽ truy vấn bộ sưu tập để xem liệu Khóa có tồn tại hay không, sau đó người ta sẽ thực hiện chèn nếu khóa không tồn tại. Hai hoạt động này không phải là luồng an toàn mặc dù, giữa truy vấn của ContainsKey và thao tác Thêm một luồng khác có thể đã thực hiện chèn khóa đó để có điều kiện chủng tộc.

Nói cách khác, hoạt động của bộ sưu tập là an toàn chỉ - nhưng việc sử dụng nó không nhất thiết. Trong trường hợp này, người ta cần chuyển đổi trở lại các kỹ thuật khóa truyền thống (mutex/monitor/semaphore ...) để đạt được an toàn luồng để bộ sưu tập đồng thời đã mua cho bạn không có gì về an toàn đa luồng (nhưng có thể tệ hơn cho hiệu năng) .

+0

Tôi đã suy nghĩ cùng một dòng. Vấn đề đặt nếu vắng mặt, nơi bạn có thể kết thúc với 2 đối tượng trong bộ sưu tập của bạn, nơi không có trước đó. Cảm ơn +1. – Andrew

+0

@ saret: Mặc dù vậy, thật khó để cung cấp các chức năng cần thiết cho việc sử dụng an toàn cho luồng đúng? Tôi sẽ nghĩ rằng nếu từ điển không cần phải giữ giá trị "Không có gì", mọi thứ có thể được thực hiện với một điều tra viên, một tài sản thay đổi dài, và một phương pháp làm việc tương tự như Threading.Interlocked.CompareExchange. Việc thêm các giá trị "Không có gì" tạo ra sự phức tạp hơn một chút, nhưng không quá nhiều. – supercat

+0

@supercat, một cách có thể tốt hơn là cung cấp các phương thức trên chính bộ sưu tập mà làm việc trong một khóa (chẳng hạn như thực hiện hành động/func trong khóa), hoặc cung cấp chức năng như InsertIfNotExists – saret

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