2010-10-22 58 views
10
lock(dictionaryX) 
{ 
    dictionaryX.TryGetValue(key, out value); 
} 

đang khóa cần thiết trong khi thực hiện tra cứu từ điển?có cần thiết để tra cứu từ điển không?

Chương trình này đa luồng và thêm khóa/giá trị vào dict. dict đang bị khóa.

+1

nếu câu hỏi của bạn là nghiêm trọng và liên quan đến các chương trình đa luồng, hãy chắc chắn rằng bạn đề cập một cách rõ ràng rằng trong câu hỏi của bạn. –

+3

câu hỏi của tôi không nghiêm trọng như bình luận của bạn. – DarthVader

Trả lời

2

Chỉ cần khóa khi bạn đang đồng bộ hóa quyền truy cập vào tài nguyên giữa các chuỗi. Miễn là không có chủ đề mulitple tham gia sau đó khóa là không cần thiết ở đây.

Trong ngữ cảnh cập nhật và đọc giá trị từ nhiều luồng, có khóa là hoàn toàn cần thiết. Trong thực tế, nếu bạn đang sử dụng 4.0, bạn nên xem xét chuyển sang một trong những bộ sưu tập được thiết kế đặc biệt để truy cập đồng thời.

+2

ngay cả khi tra cứu? trong khi viết, nó đã bị khóa. – DarthVader

+1

@ user177883 không hoạt động trên 'Dictionary' yêu cầu khóa trừ khi có nhiều chủ đề liên quan đến – JaredPar

+0

Tôi cũng đã đề cập rằng từ điển đang bị khóa trong khi thêm dữ liệu vào nó. nhưng tại sao tôi lại khóa nó lại, trong khi tra cứu? có nghĩa là, tôi vẫn có thể tra cứu trong khi dict bị khóa để viết? – DarthVader

0

Có, bạn nên khóa nếu từ điển này là tài nguyên được chia sẻ giữa nhiều hơn một chuỗi. Điều này đảm bảo rằng bạn nhận được giá trị chính xác và chuỗi khác không xảy ra để thay đổi giá trị giữa đường trong suốt cuộc gọi Lookup của bạn.

10

Như đã đề cập here:

Sử dụng TryGetValue() mà không khóa là không an toàn. Từ điển tạm thời ở trạng thái làm cho nó không phù hợp để đọc trong khi một luồng khác đang viết từ điển. Một từ điển sẽ tự tổ chức lại theo thời gian vì số lượng mục nhập từ đó chứa. Khi bạn đọc vào thời điểm chính xác tổ chức lại này diễn ra, bạn sẽ gặp nguy cơ tìm ra giá trị sai cho khóa khi các nhóm đã được cập nhật nhưng chưa phải là mục nhập giá trị.

CẬP NHẬT: hãy xem phần "An toàn chủ đề" của this page.

+0

Điều này chỉ đúng khi luồng có liên quan. Nếu không có luồng không có khóa là cần thiết. – JaredPar

+3

OP được đề cập một cách rõ ràng rằng hoạt động này đang diễn ra trong môi trường đa luồng. –

+1

Tôi đồng ý. Nhưng tác giả câu hỏi có nghĩa là sử dụng khóa trong môi trường đa luồng. – Kamyar

1

Có, bạn cần khóa từ điển để truy cập trong môi trường đa luồng. Việc viết vào từ điển không phải là nguyên tử, vì vậy nó có thể thêm khóa, nhưng không phải là giá trị. Trong trường hợp đó khi bạn truy cập nó, bạn có thể nhận được một ngoại lệ.

+0

không phải để viết, để đọc. – DarthVader

+0

@ user177 có, tôi đã nói về việc đọc. Khi tôi đề cập đến viết, đó là một ví dụ về những gì có thể xảy ra trong thời gian bạn đang cố đọc. –

3

Như với nhiều câu hỏi tinh tế trong lập trình, câu trả lời là: Không nhất thiết.

Nếu bạn chỉ thêm giá trị làm khởi tạo, thì việc đọc tiếp theo không cần phải được đồng bộ hóa. Nhưng, mặt khác, nếu bạn sẽ đọc và viết vào mọi lúc, thì tuyệt đối bạn cần phải bảo vệ tài nguyên đó.

Tuy nhiên, toàn bộ lock có thể không phải là cách tốt nhất, tùy thuộc vào số lượng lưu lượng truy cập mà Từ điển của bạn nhận được. Hãy thử một ReaderWriterLockSlim nếu bạn đang sử dụng .NET 3.5 trở lên.

+2

+1: Trong khi nó là giá trị một shot nó là * rất * có khả năng 'ReaderWriterLockSlim' sẽ chậm hơn so với một' cũ 'đồng bằng trong tình huống này ... chậm hơn rất nhiều trong thực tế.Trong các thử nghiệm cá nhân của riêng tôi, tôi đã phát hiện ra rằng 'ReaderWriterLockSlim' có khoảng 5x chi phí và' ReaderWriterLock' cũ khoảng 15x. Một khóa RW có phạm vi ứng dụng hẹp hơn nhiều so với một khóa 'bình thường' và vì vậy nó sẽ chậm hơn trong hầu hết các tình huống. Ổ khóa RW thực sự tỏa sáng khi khóa được giữ trong một thời gian dài và số lượng nhà văn đông hơn số lượng độc giả bằng một biên độ rộng. Đó là giá trị điểm chuẩn mặc dù. –

3

Nếu bạn có nhiều chuỗi truy cập từ điển, bạn cần phải khóa các cập nhật và tìm kiếm. Lý do bạn cần khóa khi tra cứu là có thể có bản cập nhật diễn ra cùng lúc khi bạn thực hiện tra cứu và từ điển có thể ở trạng thái không ổn định trong khi cập nhật. Ví dụ, hãy tưởng tượng rằng bạn đã một thread làm điều này:

if (myDictionary.TryGetValue(key, out value)) 
{ 
} 

và một thread riêng biệt được làm điều này:

myDictionary.Remove(key); 

Điều gì có thể xảy ra là các chủ đề làm TryGetValue xác định rằng mục là trong từ điển, nhưng trước khi nó có thể lấy được mục, chủ đề khác sẽ loại bỏ nó.Kết quả sẽ là chủ đề thực hiện tra cứu sẽ ném một ngoại lệ hoặc TryGetValue sẽ trả lại true nhưng value sẽ là null hoặc có thể là đối tượng không khớp với khóa.

Đó chỉ là một điều có thể xảy ra. Một cái gì đó tương tự như thảm họa có thể xảy ra nếu bạn đang làm một tra cứu trên một sợi và một sợi khác làm một thêm giá trị mà bạn đang cố gắng tìm kiếm.

1

Nếu bạn đang sử dụng .Net 4, bạn có thể thay thế bằng ConcurrentDictionary để thực hiện việc này một cách an toàn. Có các bộ sưu tập tương tự khác, được ưu tiên khi bạn cần truy cập đa luồng, trong số System.Collection.Concurrent namespace.

Không sử dụng khóa cuộn riêng nếu đây là tùy chọn cho bạn.

2

Sử dụng new ConcurrentDictionary<TKey, TValue> object và bạn có thể quên phải thực hiện bất kỳ khóa nào.

+0

Bạn không thể quên khóa tất cả. Nếu bạn làm điều này trên ConcurrentDictionary: 'if (concDic.Contains (" key "))' 'concDic [" key "]. Do();' Bạn có thể có ngoại lệ, vì khóa này có thể bị xóa giữa if và Do(). – Coder14

0

Có, bạn phải khóa nếu bạn có cập nhật đa luồng trên từ điển đó. Kiểm tra bài tuyệt vời này để biết chi tiết: “Thread safe” Dictionary(TKey,TValue)

Nhưng kể từ ConcurrentDictionary<> giới thiệu bạn có thể sử dụng nó hoặc thông qua NET 4 hoặc bằng cách sử dụng Rx trong 3.5 (nó chứa System.Threading.dll với thực hiện cho bộ sưu tập thread-safe mới)

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