首頁 >後端開發 >C#.Net教程 >使用ConcurrentDictionary多執行緒同步字典集合實例詳解

使用ConcurrentDictionary多執行緒同步字典集合實例詳解

零下一度
零下一度原創
2017-06-24 09:48:2414325瀏覽

在之前一段時間裡面,我的基類多數使用lock和Hashtable組合實現多線程內緩存的衝突處理,不過有時候使用這兩個搭配並不盡如人意,偶爾還是出現了集合已經加入的異常,對程式碼做多方的處理後依然如故,最後採用了.NET 4.0後才引入的ConcurrentDictionary多線程同步字典集合,問題順利解決。

1、使用lock和Hashtable組合實作

在我的基底類別裡面,建構業務對象,一般用BLLFactory.Instance就可以獲得對應業務對象的應用了。

var result = BLLFactory<Customer>.Instance.FindFirst();
Console.WriteLine(result.ToJson());

因此使用BLLFactory.Instance這個建構物件後,把它們放到HashTable裡面,由於需要設計多執行緒衝突處理,因此需要使用lock物件來實現鎖定的處理。

HashTable表示鍵/值對的集合。在.NET Framework中,Hashtable是System.Collections命名空間提供的一個容器,用於處理和表現類似key-value的鍵值對,其中key通常可用於快速查找,同時key是區分大小寫;value用於儲存對應於key的值。 Hashtable中key-value鍵值對均為object型,所以Hashtable可以支援任何型別的keyvalue鍵值對,任何非 null 物件都可以當作鍵或值。

使用這種方式,偶爾在Web端,還是出現多執行緒存取衝突的問題,為此我們也可以使用多執行緒的測試程式碼來進行測試重現錯誤,

            try{
                List<Thread> list = new List<Thread>();for (int i = 0; i < 10; i++)
                {
                    Thread thread = new Thread(() =>{var result = BLLFactory<Customer>.Instance.FindFirst();
                        Console.WriteLine(result.ToJson());
                        Console.WriteLine();
                    });

                    list.Add(thread);
                }for (int i = 0; i < list.Count; i++)
                {
                    list[i].Start();
                }
            }catch(Exception ex)
            {
                LogTextHelper.Error(ex);
            }

追蹤程式碼得到錯誤訊息如下所示。

因此,從上面程式碼可以看到,使用lock(syncRoot)也無法出現的多執行緒衝突問題。

 

2、使用ConcurrentDictionary取代Hashtable

ConcurrentDictionary是.net4.0推出的一套執行緒安全集合裡的其中一個,和它一起被發行的還有ConcurrentStack,ConcurrentQueue等類型,它們的單線程版本(線程不安全的,Queue,Stack,Dictionary)我們一定不會陌生。 ConcurrentDictionary<TKey, TValue> 可由多個執行緒同時訪問,且執行緒安全,用法同Dictionary很多相同,但是多了一些方法。 ConcurrentDictionary 屬於System.Collections.Concurrent 命名空間。

System.Collections.Concurrent 命名空間提供多個執行緒安全集合類別。當有多個執行緒並發存取集合時,應使用這些類別來取代 System.Collections 和 System.Collections.Generic 命名空間中的對應類型

ConcurrentDictionary這個類別提供了下面幾個方法,用於對集合的處理

public bool TryAdd(TKey key, TValue value)public bool TryUpdate(TKey key, TValue newValue, TValue comparisonValue)public TValue this[TKey key] { get; set; }public TValue AddOrUpdate(TKey key, Func<TKey, TValue> addValueFactory, Func<TKey, TValue, TValue> updateValueFactory)    
public TValue AddOrUpdate(TKey key, TValue addValue, Func<TKey, TValue, TValue> updateValueFactory)public TValue GetOrAdd(TKey key, TValue value)public TValue GetOrAdd(TKey key, Func<TKey, TValue> valueFactory)

使用ConcurrentDictionary來取代Hashtable,讓我們來看看BLLFactory的類別的實作程式碼如下所示。

    /// <summary>/// 对业务类进行构造的工厂类/// </summary>/// <typeparam name="T">业务对象类型</typeparam>public class BLLFactory<T> where T : class{//采用ConcurrentDictionary线程安全的集合类来缓存,替代Hashtableprivate static ConcurrentDictionary<string, object> conCurrentCache = new ConcurrentDictionary<string, object>(); /// <summary>/// 创建或者从缓存中获取对应业务类的实例/// </summary>public static T Instance
        {get{string CacheKey = typeof(T).FullName;return (T)conCurrentCache.GetOrAdd(CacheKey, s =>{var bll = Reflect<T>.Create(typeof(T).FullName, typeof(T).Assembly.GetName().Name); //反射创建,并缓存return bll;
                });
            }
        }
    }

我們可以看到程式碼簡化了很多,而且使用前面的多執行緒測試程式碼,也順利取得數據,不會出現異常了。

執行程式碼可以順利實現,不會出現先前使用Hashtable出現的多執行緒存取異常了。

以上就是引入ConcurrentDictionary替代Hashtable對多執行緒的物件快取處理,能夠順利解決問題的時候,發現其存取效率也是較之前有所提高,一舉兩得。

 

以上是使用ConcurrentDictionary多執行緒同步字典集合實例詳解的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述:
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn
上一篇:一個很強大的控制項--PropertyGrid下一篇:一個很強大的控制項--PropertyGrid

相關文章

看更多