2009-11-28 33 views
12

Tôi không quá chắc chắn, vì vậy tôi nghĩ tôi sẽ hỏi. Việc xóa và thêm các mục vào một đối tượng System.Collections.Generic.List<> có phải là không an toàn không?Danh sách <T> đồng thời xóa và thêm

tình hình của tôi:

Khi một kết nối được nhận, nó được thêm vào danh sách, nhưng cũng đồng thời, có một công nhân đó là loại bỏ các kết nối chết và như vậy.

Có sự cố không? lock có hoạt động không? Tôi cũng muốn biết liệu tôi có được phép sử dụng khóa trên đối tượng danh sách với phương thức Foreach<> hay không.

+0

Hãy xem http://stackoverflow.com/questions/6601611/no-concurrentlistt-in-net-4-0 - câu trả lời đáng đọc. –

Trả lời

28

Có, việc thêm và xóa các mục khỏi List<> không phải là chủ đề an toàn, vì vậy bạn cần đồng bộ hóa quyền truy cập, ví dụ sử dụng lock.

Nhớ rằng từ khóa lock không có cách nào khóa đối tượng mà bạn sử dụng làm số nhận dạng, nó chỉ ngăn hai chủ đề nhập cùng một khối mã cùng một lúc. Bạn sẽ cần khóa xung quanh tất cả mã truy cập danh sách, sử dụng cùng một đối tượng làm số nhận dạng.

+4

+1 Giải thích hay. –

+0

Điều gì về loại bỏ như vậy trong 'List.Foreach <>', nó vẫn yêu cầu một khóa? – TheAJ

+0

@AJ: Có, bạn cần một khóa xung quanh * tất cả * quyền truy cập vào danh sách. Nếu bạn đang lặp qua danh sách và một chủ đề khác loại bỏ một mục, bạn sẽ nhận được một ngoại lệ (hoặc một sự cố trong một số trường hợp). – Guffa

2

List<T> không an toàn cho luồng, vì vậy có, bạn sẽ cần kiểm soát quyền truy cập vào danh sách bằng khóa. Nếu bạn có nhiều chủ đề truy cập vào Danh sách, hãy chắc chắn rằng bạn có tất cả các chủ đề tôn trọng khóa hoặc bạn sẽ có vấn đề. Cách tốt nhất để làm điều này là để phân lớp danh sách để khóa xảy ra tự động, nếu không bạn sẽ có nhiều khả năng sẽ bị mất cuối cùng.

+0

Đó không phải là cách tốt nhất. Nó không chỉ vì việc thực hiện của List - cũng là giao diện của nó không được thiết kế để sử dụng bởi nhiều luồng. Nếu bạn muốn có một cách an toàn để làm việc này, bạn cũng cần một giao diện hoàn toàn khác. Danh sách phải là chi tiết triển khai nội bộ, được ẩn từ người dùng. http://blogs.msdn.com/jaredpar/archive/2009/02/11/why-are-thread-safe-collections-so-hard.aspx –

-1

Trên thực tế, đôi khi Danh sách <> là thread-an toàn, và đôi khi không, theo Microsoft:

thành viên Công tĩnh của loại này là chủ đề an toàn. Bất kỳ thành viên cá thể nào đều là không được bảo đảm là chuỗi an toàn.

nhưng trang đó tiếp tục nói:

Tiến hành thống kê thông qua một bộ sưu tập là về bản chất không phải là một thread-safe thủ tục. Trong trường hợp hiếm hoi khi một số đếm cạnh tranh với một hoặc nhiều hơn quyền truy cập ghi, cách duy nhất để đảm bảo an toàn chủ đề là khóa bộ sưu tập trong toàn bộ số liệt kê. Để cho phép bộ sưu tập được truy cập bằng nhiều luồng cho việc đọc và viết , bạn phải triển khai đồng bộ hóa của riêng mình.

+4

Không, Danh sách không bao giờ là chủ đề an toàn. Đó chỉ là một văn bản tiêu chuẩn được sử dụng cho tất cả các lớp thông thường. Vì lớp List không có bất kỳ thành viên tĩnh nào cả, nên không có thành viên nào an toàn. – Guffa

+0

Tôi đồng ý rằng anh ấy chắc chắn nên sử dụng khóa. Cảm ơn bạn đã làm rõ. – DOK

+1

@Guffa: Tôi khá chắc chắn 'Danh sách ' là chủ đề an toàn trong sự hiện diện của nhiều độc giả và không có nhà văn. Rất hiếm khi các bộ sưu tập không an toàn chỉ với sự hiện diện của nhiều độc giả mà mức độ an toàn luồng được giả thiết trong trường hợp không có tài liệu khác; Tuy nhiên, các bộ sưu tập duy nhất tôi muốn nói là "không bao giờ" thread-an toàn là những thứ như bộ sưu tập lười biếng, nơi hai đồng thời "đọc" truy cập có thể gây ra sửa đổi mâu thuẫn. – supercat

-1

Chắc chắn việc sử dụng khóa cho mã cụ thể làm cho chuỗi đó an toàn, nhưng tôi không đồng ý với chủ đề này cho trường hợp hiện tại.

Bạn có thể triển khai phương thức Đồng bộ hóa để làm cho chuỗi bộ sưu tập an toàn. Điều này link giải thích lý do và cách thực hiện điều đó.

Một cách tiếp cận hoàn toàn có lập trình khác được đề cập trong link này, mặc dù tôi chưa bao giờ thử nghiệm trực tiếp nhưng nó sẽ hoạt động.

btw, một trong những mối quan tâm lớn hơn là, bạn có đang cố gắng duy trì một thứ gì đó như hồ bơi kết nối theo sở hữu của mình không? nếu có thì tại sao?

Tôi lấy lại câu trả lời của mình. Sử dụng khóa trong câu trả lời tốt hơn bằng cách sử dụng phương pháp này.

+0

Đồng bộ hóa là một ý tưởng tồi. Xem http://blogs.msdn.com/b/jaredpar/archive/2009/02/11/why-are-thread-safe-collections-so-hard.aspx –

+0

Tôi đã bỏ phiếu vì "bạn lấy lại" :) mà không xóa, mà bạn có thể đã làm. Nhưng để nó ở đó có thể sâu sắc cho người khác. –

4

Đồng thời của câu hỏi, thì chẳng .NET Framework 4, nhưng những người đang phải đối mặt với vấn đề bây giờ nên cố gắng sử dụng các bộ sưu tập từ System.Collections.Concurrent namespace để đối phó với thread-safe vấn đề

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