2014-06-16 13 views
8
  1. Tôi có một ConcurrrentDictionary được tạo như một đối tượng ứng dụng trong ứng dụng web của tôi. và được chia sẻ giữa các phiên. (Về cơ bản phục vụ như một kho lưu trữ.)
  2. Đôi khi một mục mới được thêm vào từ điển bởi bất kỳ phiên có sẵn nào.

Allow Admin Xem ChỉKhi Iterating Over ConcurrentDictionary và chỉ đọc, là ConcurrentDictionary bị khóa?

Bây giờ, tôi muốn cho phép một admin để liệt kê tất cả các giá trị trong từ điển, nhưng quản trị sẽ không thêm hoặc xoá các mục, thay vào đó tôi sẽ chỉ cung cấp một cách để quản trị viên xem các mục qua đọc của bộ sưu tập bằng cách lặp qua các mục.

(Pseudo) Mã sẽ giống như này:

foreach (var e in EmployeeCache.Instance.AllEmployees) 
{ 
    Console.WriteLine(e.Key); 
} 

Câu hỏi của tôi là thế này:

Nếu tôi lặp qua các mục nào ConcurrentDictionary bị khóa trong khi nó đang được đọc từ? Nói cách khác, là ConcurrentDictionary bị khóa để các phiên khác sẽ không thể thêm hoặc loại bỏ trong khi mã quản trị chỉ đơn giản là lặp qua ConcurrentDictionary?

Nếu không bị khóa, bạn có thể giải thích

Nếu bạn tin rằng nó không bị khóa, bạn có thể cho một bản tóm tắt nhanh chóng của nó như thế nào thực hiện điều này? Ví dụ, nó có tạo ra một bản sao của ConcurrentDictionary cho hành động chỉ đọc và sau đó cho phép đọc lặp lại - hiểu rằng những thay đổi đồng thời với từ điển thực sẽ không được nhìn thấy?

Những gì tôi đang cố gắng xác định

Tôi đang cố gắng để hiểu được tác động của việc cung cấp một xem ConcurrentDictionary có thể được làm mới thường xuyên bởi một quản trị. I E. Nếu họ làm mới nó thường xuyên đủ có thể ảnh hưởng đến hiệu suất của ứng dụng web. khi phiên đang chờ đối tượng mở khóa để họ có thể thêm/xóa các mục?

Trả lời

6

Đây là cách ConcurrentDictionary.GetEnumerator Được thực hiện:

/// <remarks> 
/// The enumerator returned from the dictionary is safe to use concurrently with 
/// reads and writes to the dictionary, however it does not represent a moment-in-time 
/// snapshot of the dictionary. The contents exposed through the enumerator may contain 
/// modifications made to the dictionary after <see cref="GetEnumerator"/> was called. 
/// </remarks> 
public IEnumerator<KeyValuePair<TKey, TValue>> GetEnumerator() 
{ 
    Node[] buckets = m_tables.m_buckets; 

    for (int i = 0; i < buckets.Length; i++) 
    { 
     // The Volatile.Read ensures that the load of the fields of 'current' 
     // doesn't move before the load from buckets[i]. 
     Node current = Volatile.Read<Node>(ref buckets[i]); 

     while (current != null) 
     { 
      yield return new KeyValuePair<TKey, TValue>(current.m_key, current.m_value); 
      current = current.m_next; 
     } 
    } 
} 

Như bạn thấy, lặp là khóa miễn phí, và chỉ đơn giản là mang lại một cấu trúc bất biến (KeyValuePair) mà được trả lại cho người gọi cho mỗi lần lặp. Đó là lý do tại sao không thể đảm bảo ảnh chụp nhanh trong ConcurrentDictionary

Điều này chắc chắn sẽ không có hiệu ứng hiệu suất khi thêm/cập nhật giá trị mới trong khi lặp lại, nhưng nó không thể đảm bảo rằng quản trị viên của bạn sẽ thấy ảnh chụp nhanh được cập nhật nhất của từ điển.

  1. Bạn có thể duyệt các phần còn lại của mã nguồn mình qua http://sourceof.net
  2. Và bạn cũng có thể kiểm tra Inside the Concurrent Collections: ConcurrentDictionary bởi Simon Cooper.
  3. Are all of the new concurrent collections lock-free?
+1

* Yuval, Cảm ơn. Đó là những gì tôi đã tự hỏi. Cảm ơn bạn rất nhiều vì đã dành thời gian đọc bài đăng của tôi và tập trung vào những gì tôi đã hỏi. Tôi sẽ đợi, nhưng tôi sẽ đánh dấu đây là câu trả lời trong những ngày tiếp theo. Cảm ơn một lần nữa vì một câu trả lời tốt và được viết tốt. – raddevus

+0

Tại sao có 'Volatile.Read' (hàng rào bộ nhớ) cho' current = buckets [i] '? Chắc chắn, có một bình luận nhưng tôi không hiểu nó. – tigrou

+1

Tôi tìm thấy câu trả lời: Trong C# tất cả các lần đọc là không dễ bay hơi, nó có nghĩa là nếu một biến đã được thay đổi trong một chủ đề, nó vẫn có thể không được phản ánh trong một chủ đề khác (vì bộ nhớ đệm/tối ưu hóa). 'Volatile.Read' đảm bảo mới nhất, giá trị mới nhất được lấy ra. Đây là những gì chúng ta muốn ở đây trong khi đọc 'buckets [i]' – tigrou

4

Đây là những gì tài liệu đang nói:

Các điều tra viên trở về từ điển là an toàn để sử dụng đồng thời với đọc và viết vào từ điển, tuy nhiên nó không không đại diện cho một ảnh chụp khoảnh khắc-in-time của từ điển. Các nội dung được tiếp xúc qua điều tra viên có thể chứa các sửa đổi được thực hiện vào từ điển sau khi GetEnumerator được gọi.

http://msdn.microsoft.com/en-us/library/dd287131(v=vs.110).aspx

Vì vậy, nếu bạn muốn "chụp" hành vi, bạn sẽ phải tạo một bản sao của bộ sưu tập Keys và lặp qua các bản sao, nếu không bạn sẽ lặp qua chủ đề có thể thay đổi bộ sưu tập an toàn.

+0

Điều đó có thể dẫn đến một tình trạng chủng tộc khi "ảnh chụp" Điều quan trọng là không còn hiện diện dù, vì vậy đó không phải là thực sự là một bản chụp. – urbanhusky

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