2009-04-01 24 views
42

Từ trang web sau đây:Tại sao Danh sách <T> không an toàn cho chủ đề?

http://crfdesign.net/programming/top-10-differences-between-java-and-c

Thật không may, List<> không phải là thread-safe (‘s ArrayList C# và Java Vector là thread-safe). C# cũng có Hashtable; phiên bản chung là:

Điều gì khiến cho List<T> không an toàn cho chủ đề? Có vấn đề thực hiện trên một phần của bộ máy .NET không? Hoặc là generics không thread-safe?

+0

Theo MSDN [ArrayList] (http://msdn.microsoft.com/en-us/library/system.collections. arraylist.aspx # threadSafetyToggle) và [List (Of T)] (http://msdn.microsoft.com/en-us/library/6sh2ey19.aspx#threadSafetyToggle) có cùng một luồng an toàn. 'ArrayList' không cung cấp trình bao bọc [Synchronized] (http://msdn.microsoft.com/en-us/library/system.collections.arraylist.synchronized.aspx). –

Trả lời

67

Bạn thực sự cần phân loại loại Vector an toàn chủ đề của Java. Javas Vector là an toàn để được sử dụng từ nhiều chủ đề bởi vì nó sử dụng đồng bộ hóa trên các phương pháp. Nhà nước sẽ không bị hỏng.

Tuy nhiên, tính hữu dụng của vectơ Java bị giới hạn từ nhiều chuỗi mà không cần đồng bộ hóa bổ sung. Ví dụ: xem xét hành vi đọc đơn giản một phần tử từ một vector

Vector vector = getVector(); 
if (vector.size() > 0) { 
    object first = vector.get(0); 
} 

Phương pháp này sẽ không làm hỏng trạng thái của vectơ, nhưng cũng không đúng. Không có gì ngăn chặn một luồng khác từ việc đột biến vectơ ở giữa câu lệnh if một lời gọi get(). Mã này có thể và sẽ cuối cùng không thành công do điều kiện chủng tộc.

Loại đồng bộ hóa này chỉ hữu ích trong một loạt các trường hợp và nó chắc chắn không rẻ. Bạn trả một mức giá đáng chú ý để đồng bộ hóa ngay cả khi bạn không sử dụng nhiều luồng.

. Net đã chọn không trả giá này theo mặc định cho một trường hợp chỉ có tính hữu ích hạn chế. Thay vào đó, nó đã chọn để thực hiện một danh sách khóa miễn phí. Tác giả chịu trách nhiệm thêm bất kỳ đồng bộ hóa nào. Nó gần gũi hơn với mô hình của C++ là "chỉ trả tiền cho những gì bạn sử dụng"

Gần đây tôi đã viết một vài bài viết về sự nguy hiểm của việc sử dụng các bộ sưu tập chỉ với đồng bộ nội bộ như vector của Java.

Reference Vector chủ đề an toàn: http://www.ibm.com/developerworks/java/library/j-jtp09263.html

+13

Ghi chú nhỏ: "khóa tự do" ngụ ý "được đồng bộ hóa mà không có bất kỳ khóa nào", không phải "không có khóa". http://en.wikipedia.org/wiki/Lock_free –

+0

Tôi đồng ý với Strilanc: Tôi phải sử dụng thuật ngữ "khóa miễn phí" của bạn. –

+0

Các phương pháp như "Đếm" có thể hoàn toàn hợp lý và được sử dụng hợp pháp trên bộ sưu tập an toàn chỉ với mục đích quyết định không làm phiền điều gì đó. Ví dụ, nếu cần thực hiện một số thao tác sử dụng hai mục được lấy từ một hàng đợi, một mẫu hoàn toàn hợp lý có thể sử dụng một thuộc tính để kiểm tra số đếm (với hàng rào đọc thay vì khóa) và, nếu đếm là đủ , lấy khóa và kiểm tra số lần nữa. Nếu vẫn đủ, thực hiện thao tác; bằng cách khác bỏ qua nó. Nhả khóa trong mọi trường hợp. – supercat

20

Tại sao sẽ tính năng này an toàn cho chủ đề? Không phải mọi lớp đều là. Thực tế, theo mặc định, các lớp học là không phải là an toàn chỉ.

Làm chủ đề an toàn có nghĩa là mọi hoạt động sửa đổi danh sách sẽ cần phải được khóa liên động với truy cập đồng thời. Điều này sẽ cần thiết ngay cả đối với những danh sách sẽ chỉ được sử dụng bởi một chuỗi đơn. Điều đó sẽ rất không hiệu quả.

9

Nó chỉ đơn giản là một quyết định thiết kế để thực hiện các loại không đề an toàn. Bộ sưu tập cung cấp thuộc tính SyncRoot của giao diện ICollection và phương pháp Synchronized() trên một số bộ sưu tập để đồng bộ hóa rõ ràng các loại dữ liệu.

Sử dụng SyncRoot để khóa đối tượng trong môi trường đa luồng.

lock (collection.SyncRoot) 
{ 
    DoSomething(collection); 
} 

Sử dụng collection.Synchronized() để lấy trình bao bọc an toàn cho bộ sưu tập.

+4

Xem các bài báo của JaredPar để giải thích tại sao điều này gần như chắc chắn không phải là những gì bạn muốn làm. –

2

Để đảm bảo an toàn cho chuỗi chính xác, List<> và các loại bộ sưu tập khác sẽ cần phải thay đổi. Với các phần mở rộng song song cho .NET sắp ra trong .NET 4.0, chúng ta sẽ thấy các phiên bản an toàn của các bộ sưu tập được sử dụng phổ biến nhất. Jon Skeet chạm vào một số điều này.

2

Khả năng điều kiện chủng tộc mà JaredPar đề cập là hậu quả đáng sợ khi dựa vào sự an toàn của luồng được đề xuất của Vector. Đó là loại điều mà kết quả trong "mỗi thứ chín thứ chín các ứng dụng làm một cái gì đó kỳ lạ" -sort của báo cáo lỗi mà sẽ lái xe bạn điên.

Có một số thực sự thread-safe bộ sưu tập coming in .Net 4, với tác dụng phụ thú vị mà chúng cho phép đơn luồng modification of the collection while enumerating, nhưng có một performance hit mà đi kèm với thread-an toàn, đôi khi một khá lớn. Vì vậy, điều hợp lý cho một nhà phát triển khung làm là giữ cho lớp càng hoạt động càng tốt cho 95% người dùng có thể sẽ không làm việc theo luồng và dựa vào những người làm nhiều chủ đề để biết họ có gì phải làm để giữ an toàn.

0

sử dụng SynchronizedCollection nó cũng cung cấp một Constructor-Parameter sử dụng một đồng bộ chia sẻ :)

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