2013-08-21 74 views
9

Tôi đang viết thư viện lớp di động nhắm mục tiêu .NET 4.5, ứng dụng Windows Store và Windows Phone 8. Tôi cần một cơ chế bộ nhớ trong bộ nhớ hiệu quả, vì vậy tôi đã nghĩ đến việc sử dụng ConcurrentDictionary<K,V>, nhưng nó không có sẵn trong WP8.Thay thế cho ConcurrentDictionary cho thư viện lớp di động

Sẽ có nhiều lần đọc và viết tương đối ít, vì vậy lý tưởng tôi muốn một bộ sưu tập hỗ trợ đọc không có khóa từ nhiều luồng và viết bằng một chuỗi đơn. Không chung chung Hashtable có thuộc tính đó, according to MSDN, nhưng tiếc là không có sẵn trong PCL ...

Có một lớp thu thập khác có sẵn trong PCL khớp với yêu cầu này không? Nếu không, điều gì sẽ là một cách tốt để đạt được an toàn luồng mà không cần khóa để đọc? (Khóa cho viết là OK, vì nó sẽ không xảy ra quá thường xuyên)


EDIT: nhờ hướng dẫn JaredPar, tôi cuối cùng đã thực hiện bộ nhớ cache của tôi trong một thời trang hoàn toàn lock-free, sử dụng ImmutableDictionary<TKey, TValue> từ Microsoft.Bcl.Immutable:

class Cache<TKey, TValue> 
{ 
    private IImmutableDictionary<TKey, TValue> _cache = ImmutableDictionary.Create<TKey, TValue>(); 

    public TValue GetOrAdd(TKey key, [NotNull] Func<TKey, TValue> valueFactory) 
    { 
     valueFactory.CheckArgumentNull("valueFactory"); 

     TValue newValue = default(TValue); 
     bool newValueCreated = false; 
     while (true) 
     { 
      var oldCache = _cache; 
      TValue value; 
      if (oldCache.TryGetValue(key, out value)) 
       return value; 

      // Value not found; create it if necessary 
      if (!newValueCreated) 
      { 
       newValue = valueFactory(key); 
       newValueCreated = true; 
      } 

      // Add the new value to the cache 
      var newCache = oldCache.Add(key, newValue); 
      if (Interlocked.CompareExchange(ref _cache, newCache, oldCache) == oldCache) 
      { 
       // Cache successfully written 
       return newValue; 
      } 

      // Failed to write the new cache because another thread 
      // already changed it; try again. 
     } 
    } 

    public void Clear() 
    { 
     _cache = _cache.Clear(); 
    } 
} 
+0

Bạn đã xem xét viết một loại bọc một cây bất biến, và đã làm một CAS để viết? Điều đó sẽ cung cấp cho bạn khóa đọc miễn phí, viết CAS và bạn chỉ có thể sử dụng cây AVL bất biến của Eric làm cấu trúc sao lưu http://blogs.msdn.com/b/ericlippert/archive/2008/01/21/immutability-in- c-part-nine-learning-plus-my-avl-tree-implementation.aspx – JaredPar

+0

@JaredPar, "CAS" là gì? –

+0

CAS = so sánh và hoán đổi. – JaredPar

Trả lời

4

Một tùy chọn để xem xét là viết một mặt tiền mỏng trên cây tìm kiếm không thay đổi. Có một số cây tìm kiếm bất biến có sẵn trên web để bạn chọn. Tôi thường căn cứ của tôi tắt của bài lớn Eric Lipperts về chủ đề

Sử dụng điều này như cấu trúc dữ liệu ủng hộ sẽ cung cấp cho bạn khóa miễn phí. Viết cho cây có thể được thực hiện trong một khóa thời trang miễn phí với CAS là tốt. Điều này sẽ chậm hơn một chút so với ConcurrentDictionary vì tra cứu là O (Log (N)) thay vì tiếp cận O (1). Nhưng nó nên làm các thủ thuật cho bạn

+0

Giải pháp tuyệt vời, cảm ơn! Về việc ghi khóa không cần viết, tôi không chắc chắn làm thế nào để đạt được nó ... nếu tôi không khóa và mỗi luồng của người viết tạo một bản sao khác, bản thứ hai sẽ ghi đè lên những gì người đầu tiên đã làm, phải không? –

+0

Đây là cách tôi đang sử dụng cây ngay bây giờ: https://gist.github.com/thomaslevesque/92ad1f8643dfa7a2970a –

+0

@ThomasLevesque hãy xem các chỉnh sửa mà tôi đã thực hiện. Tôi đã cố giải thích logic trong các bình luận https://gist.github.com/jaredpar/20fbdb7ad7fbbb4bd82d – JaredPar

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