使用ConcurrentDictionary多線程同步字典集合執行個體詳解

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

1、使用lock和Hashtable組合實現

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

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

因此使用BLLFactory<T>.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出現的多線程訪問異常了。

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.