2012-06-19 27 views
19

Tôi tự hỏi, nếu phương pháp mở rộng LINQ là nguyên tử? Hoặc tôi có cần lock bất kỳ đối tượng IEnumerable nào được sử dụng trên các chuỗi, trước bất kỳ loại lặp nào không?Phương pháp Linn IEnumerable Linq có an toàn không?

Tuyên bố biến là volatile có ảnh hưởng gì đến điều này không?

Tóm lại, thao tác nào sau đây là tốt nhất, an toàn luồng, hoạt động?

1- Nếu không có bất kỳ khóa:

IEnumerable<T> _objs = //... 
var foo = _objs.FirstOrDefault(t => // some condition 

2- Bao gồm báo cáo khóa:

IEnumerable<T> _objs = //... 
lock(_objs) 
{ 
    var foo = _objs.FirstOrDefault(t => // some condition 
} 

3- Tuyên bố biến như dễ bay hơi:

volatile IEnumerable<T> _objs = //... 
var foo = _objs.FirstOrDefault(t => // some condition 
+0

Chúng không phải là chủ đề an toàn. Xem http://stackoverflow.com/questions/9995266/how-to-create-a-thread-safe-generic-list – stuartd

Trả lời

20

Giao diện IEnumerable<T> không phải là chủ đề an toàn. Xem tài liệu trên http://msdn.microsoft.com/en-us/library/s793z9y2.aspx, trong đó nêu rõ:

Điều tra viên vẫn hợp lệ miễn là bộ sưu tập không thay đổi. Nếu các thay đổi được thực hiện đối với bộ sưu tập, chẳng hạn như thêm, sửa đổi hoặc xóa các phần tử, thì điều tra viên bị vô hiệu hóa vô hiệu và hành vi của nó không được xác định.

Điều tra viên không có quyền truy cập độc quyền vào bộ sưu tập; do đó, liệt kê thông qua một bộ sưu tập thực chất không phải là một thủ tục an toàn chỉ. Để đảm bảo an toàn luồng trong quá trình liệt kê, bạn có thể khóa bộ sưu tập trong toàn bộ điều tra. Để cho phép bộ sưu tập được truy cập bởi nhiều luồng để đọc và viết, bạn phải thực hiện đồng bộ hóa của riêng bạn.

LINQ không thay đổi bất kỳ điều nào trong số này.

Khóa rõ ràng có thể được sử dụng để đồng bộ hóa quyền truy cập vào các đối tượng. Bạn phải khóa các đối tượng ở khắp mọi nơi bạn truy cập nó mặc dù, không chỉ khi lặp qua nó.

Khai báo bộ sưu tập là dễ bay hơi sẽ không có tác động tích cực. Nó chỉ dẫn đến một rào cản bộ nhớ trước khi đọc và sau khi ghi tham chiếu đến bộ sưu tập. Nó không đồng bộ hóa việc đọc hoặc ghi bộ sưu tập.

7

Tóm lại, chúng không phải là sợi chỉ an toàn như đã đề cập ở trên.

Tuy nhiên, điều đó không có nghĩa là bạn phải khóa trước "mọi loại lặp lại".

Bạn cần phải đồng bộ hóa tất cả các thao tác thay đổi bộ sưu tập (thêm, sửa đổi hoặc loại bỏ các phần tử) với các thao tác khác (thêm, sửa đổi, xóa thành phần hoặc đọc phần tử).

Nếu bạn chỉ thực hiện đồng thời các thao tác đọc trên bộ sưu tập, không cần khóa. (để chạy các lệnh LINQ như Trung bình, Chứa, ElementAtOrDefault tất cả cùng nhau sẽ ổn)

Nếu các phần tử trong bộ sưu tập có độ dài từ máy, chẳng hạn như Int trên hầu hết các máy tính 32 bit, thì thay đổi giá trị của phần tử đó đã được thực hiện một cách nguyên tử.Trong trường hợp này không thêm hoặc xóa các phần tử khỏi bộ sưu tập mà không khóa, nhưng các giá trị sửa đổi có thể không sao, nếu bạn có thể xử lý một số yếu tố không xác định trong thiết kế của bạn.

Cuối cùng, bạn có thể xem xét khóa hạt mịn trên các phần tử riêng lẻ hoặc các phần của bộ sưu tập, thay vì khóa toàn bộ bộ sưu tập.

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