轉載:https://www.cnblogs.com/wuhuacong/p/6934851.html
在之前一段時間里面,我的基類多數使用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執行緒安全的集合類來快取,替代Hashtable
private 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對多執行緒的物件快取處理,能夠順利解決問題的時候,發現其訪問效率也是較之前有所提高,一舉兩得,
轉載請註明出處,本文鏈接:https://www.uj5u.com/net/224886.html
標籤:.NET技术
