2011-11-22 39 views
58

Tôi có ngay trong suy nghĩ này là việc sử dụng đúng một từ điển đồng thờiđồng thời điển Cách sử dụng đúng

private ConcurrentDictionary<int,long> myDic = new ConcurrentDictionary<int,long>(); 

//Main thread at program startup 

for(int i = 0; i < 4; i++) 
{ 
    myDic.Add(i, 0); 
} 

//Seperate threads use this to update a value 

myDic[InputID] = newLongValue; 

Tôi không có ổ khóa vv và đang chỉ cập nhật các giá trị trong từ điển mặc dù nhiều chủ đề có thể cố gắng để làm y hệt.

+2

Nó phụ thuộc - không 'newLongValue' phụ thuộc vào giá trị trước đó của 'myDic [InputID]'? –

+74

1UP cho tên biến "myDic"! –

+2

bạn nên tránh truy cập bằng khóa trực tiếp 'myDic [InputID]' cho điều kiện chủng tộc. Bạn nên thử 'GetOrAdd' –

Trả lời

52

Điều đó phụ thuộc vào ý bạn là an toàn chỉ.

Từ MSDN - How to: Add and Remove Items from a ConcurrentDictionary:

ConcurrentDictionary<TKey, TValue> được thiết kế cho các kịch bản đa luồng. Bạn không phải sử dụng khóa trong mã của mình để thêm hoặc xóa các mục khỏi bộ sưu tập. Tuy nhiên, nó luôn luôn có thể cho một chủ đề để lấy một giá trị, và một luồng khác để cập nhật ngay bộ sưu tập bằng cách cho cùng một khóa một giá trị mới.

Vì vậy, có thể nhận được một số không phù hợp xem giá trị của một mục trong từ điển.

+1

Đó là một điểm thú vị! Bạn vẫn sẽ sử dụng một khóa trong kịch bản đó? – Jon

+0

@Jon - Tùy thuộc vào đơn đăng ký của bạn và liệu bạn có đồng ý hay không. Nhưng tôi sẽ nói rằng nếu bạn muốn xem các mục phù hợp, bạn sẽ cần phải quấn từng đọc và cập nhật một mục trong một khóa. – Oded

+4

Tôi nghĩ đây không phải là những gì mà tài liệu nói. Sự mâu thuẫn liên quan đến những gì khung nhìn chứa, nếu khung nhìn chỉ là giá trị, thì nó hoàn toàn nhất quán.Miễn là bạn nhận được giá trị của một khóa, giá trị của khóa trong từ điển có thể thay đổi. Điều này không nhất quán như giá trị DateTime.Now. –

2

Có, bạn đã đúng.

Điều đó và khả năng liệt kê từ điển trên một chuỗi trong khi thay đổi nó trên một chuỗi khác là phương tiện duy nhất tồn tại cho lớp đó.

+7

Điều tôi muốn thêm là [ở đây] (http://blogs.msdn.com/b/pfxteam/archive/2010/01/08/9945809.aspx) là thông tin hữu ích về cách thức và thời điểm sử dụng ' ConcurrentDictionary'. –

1

Cách tốt nhất để tìm ra điều này là kiểm tra tài liệu MSDN.

Đối ConcurrentDictionary trang là http://msdn.microsoft.com/en-us/library/dd287191.aspx

Dưới phần an toàn thread, nó được phát biểu "Tất cả các thành viên cộng đồng và bảo vệ của ConcurrentDictionary (Tất TKey, TValue) là thread-safe và có thể được sử dụng đồng thời từ nhiều chủ đề."

Vì vậy, từ quan điểm đồng thời, bạn vẫn ổn.

0

Tùy theo trường hợp của tôi, tôi thích sử dụng phương pháp này.

ConcurrentDictionary<TKey, TValue>.AddOrUpdate Method (TKey, Func<TKey, TValue>, Func<TKey, TValue, TValue>); 

Xem MSDN Library để biết chi tiết về cách sử dụng phương pháp.

sử dụng mẫu:

results.AddOrUpdate(
    Id, 
    id => new DbResult() { 
    Id = id, 
    Value = row.Value, 
    Rank = 1 
    }, 
    (id, v) => 
    { 
    v.Rank++; 
    return v; 
    }); 
+1

FYI: "Khi bạn cung cấp một phương pháp giá trị nhà máy (cho các phương thức GetOrAdd và AddOrUpdate), nó thực sự có thể chạy và xóa kết quả của nó sau đó (vì một số luồng khác đã thắng cuộc đua)." Thông tin thêm tại đây: https://arbel.net/2013/02/03/best-practices-for-using-concurrentdictionary/ – keremispirli

+0

Có, bạn nói đúng, vì nó được ghi chú trong phần nhận xét "Nếu bạn gọi AddOrUpdate cùng một lúc trên các chủ đề khác nhau, addValueFactory có thể được gọi nhiều lần, nhưng cặp khóa/giá trị của nó có thể không được thêm vào từ điển cho mọi cuộc gọi. " Vì vậy, bạn cần phải chắc chắn rằng bạn không tạo ra nhiều đối tượng liên tục. – Onur

+0

Và nếu bạn cần cập nhật nội dung, không thay đổi hoàn toàn đối tượng đã lưu, ví dụ để thay đổi thuộc tính của đối tượng đã thêm trước đó, phương pháp này hữu ích, nếu không bạn cần sử dụng khóa hoặc phương pháp đồng bộ khác. – Onur

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