In the past period of time, most of my base classes used a combination of lock and Hashtable to implement conflict handling for caches in multi-threads. However, sometimes using these two combinations was not satisfactory. Occasionally, the collection has been added. Exception, the problem remained the same after multiple processing of the code. Finally, the ConcurrentDictionary multi-threaded synchronized dictionary collection introduced after .NET 4.0 was used, and the problem was successfully solved.
In my base class, build the business object. Generally, you can use BLLFactory
var result = BLLFactory<Customer>.Instance.FindFirst(); Console.WriteLine(result.ToJson());
So after using BLLFactory
HashTable represents a collection of key/value pairs. In the .NET Framework, Hashtable is a container provided by the System.Collections namespace. It is used to process and represent key-value pairs. The key can usually be used for quick search, and the key is case-sensitive; the value is used for Store the value corresponding to key. The key-value pairs in Hashtable are all of object type, so Hashtable can support any type of key-value pair, and any non-null object can be used as a key or value.
Using this method, occasionally multi-threaded access conflicts still occur on the Web side. For this reason, we can also use multi-threaded test code to test and reproduce the error,
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); }
The error message obtained by the tracking code is as follows.
Therefore, as you can see from the above code, multi-thread conflict problems cannot occur even with lock(syncRoot).
ConcurrentDictionary is one of a set of thread-safe collections launched by .net4.0, and was released together with it. ConcurrentStack, ConcurrentQueue and other types, their single-threaded versions (thread-unsafe, Queue, Stack, Dictionary) will definitely be familiar to us. ConcurrentDictionary<TKey, TValue> can be accessed by multiple threads at the same time and is thread-safe. Its usage is the same as Dictionary, but with some more methods. ConcurrentDictionary belongs to the System.Collections.Concurrent namespace. The System.Collections.Concurrent namespace provides multiple thread-safe collection classes. When multiple threads are accessing a collection concurrently, these classes should be used instead of the corresponding types in the System.Collections and System.Collections.Generic namespaces ##. 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)
/// <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;
});
}
}
}
The above is the detailed content of Detailed explanation of using ConcurrentDictionary multi-thread synchronization dictionary collection example. For more information, please follow other related articles on the PHP Chinese website!