ConcurrentDictionary 与 Dictionary
Posted dragon.net
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了ConcurrentDictionary 与 Dictionary相关的知识,希望对你有一定的参考价值。
ASP.NET中ConcurrentDictionary是.Net4 增加的,与 Dictionary 最主要区别是, 前者是线程安全的集合,可以由多个线程同时并发读写Key-value。
那么 什么是线程安全?线程安全和非线程安全有什么区别?分别在什么情况下使用?
什么是线程安全 ?
线程安全就是指多线程反问时候,采用了加锁机制。
当线程A访问某个对象时候,采用了保护机制,这时候另一个线程B访问该对象不产生异常。
线程安全和非线程安全有什么区别?
非线程安全是指多线程操作同一个对象可能会出现问题。
而线程安全则是多线程操作同一个对象不会有问题。
分别在什么情况下使用?
当多线程情况下,对 全局变量、静态变量 进行访问或者操作数据的时候, 建议使用线程安全, 非线程安全有几率出现异常。
接下来放一个实例:
分别使用 ConcurrentDictionary 与 Dictionary 根据key读取value, 当key不存在的时候进行写入并读取,key存在的时候直接读取对应的value。
1.定一个接口:
public interface IGetLogger { string GetLogger(string cmdId); }
2. Dictionary 实现:
public class DictionaryLogger : IGetLogger { static Dictionary<string, string> loggreDic = new Dictionary<string, string>(); public string GetLogger(string cmdId) { if (!loggreDic.ContainsKey(cmdId)) { loggreDic.Add(cmdId, $"AAA.{cmdId}"); } return loggreDic[cmdId]; } }
3. ConcurrentDictionary 实现:
public class ConcurrentDictionaryLogger : IGetLogger { static ConcurrentDictionary<string, string> loggreDic = new ConcurrentDictionary<string, string>(); public string GetLogger(string cmdId) { if (!loggreDic.ContainsKey(cmdId)) { loggreDic.TryAdd(cmdId, $"ConcurrentDictionary.{cmdId}"); } return loggreDic[cmdId]; } }
public partial class ConcurrentDictionaryForm : Form { public ConcurrentDictionaryForm() { Console.WriteLine("欢迎来到ConcurrentDictionary线程安全"); InitializeComponent(); } /// <summary> /// 非线程安全 /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void Dictionary_Click(object sender, EventArgs e) { int threadCount = 5000; CountDownLatch latch = new CountDownLatch(threadCount); object state = new object(); for (int i = 0; i < threadCount; i++) { ThreadPool.QueueUserWorkItem(new WaitCallback(new WasteTimeDic(latch).DoSth), i); } latch.Await(); } /// <summary> /// 线程安全 /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void ConcurrentDictionary_Click(object sender, EventArgs e) { int threadCount = 5000; CountDownLatch latch = new CountDownLatch(threadCount); object state = new object(); for (int i = 0; i < threadCount; i++) { ThreadPool.QueueUserWorkItem(new WaitCallback(new WasteTime(latch).DoSth), i); } latch.Await(); } }
CountDownLatch 是一个自定义个的并发检测类:
public class CountDownLatch { private object lockObj = new Object(); private int counter; public CountDownLatch(int counter) { this.counter = counter; } public void Await() { lock (lockObj) { while (counter > 0) { Monitor.Wait(lockObj); } } } public void CountDown() { lock (lockObj) { counter--; Monitor.PulseAll(lockObj); } } } public class WasteTime { private CountDownLatch latch; public WasteTime(CountDownLatch latch) { this.latch = latch; } public void DoSth(object state) { //模拟耗时操作 //System.Threading.Thread.Sleep(new Random().Next(5) * 1000); //Console.WriteLine("state:"+ Convert.ToInt32(state)); IGetLogger conLogger = new ConcurrentDictionaryLogger(); try { Console.WriteLine($"{state}GetLogger:{conLogger.GetLogger("BBB")}"); } catch (Exception ex) { Console.WriteLine(string.Format("第{0}个线程出现问题", state)); } //执行完成注意调用CountDown()方法 this.latch.CountDown(); } } public class WasteTimeDic { private CountDownLatch latch; public WasteTimeDic(CountDownLatch latch) { this.latch = latch; } public void DoSth(object state) { //模拟耗时操作 //System.Threading.Thread.Sleep(new Random().Next(5) * 1000); //Console.WriteLine("state:"+ Convert.ToInt32(state)); IGetLogger conLogger = new DictionaryLogger(); try { Console.WriteLine($"{state}GetLoggerDic:{conLogger.GetLogger("AAA")}"); } catch (Exception ex) { Console.WriteLine(string.Format("第{0}个线程出现问题", state)); } //执行完成注意调用CountDown()方法 this.latch.CountDown(); } }
会有一定几率出现异常情况:
以上是关于ConcurrentDictionary 与 Dictionary的主要内容,如果未能解决你的问题,请参考以下文章
ConcurrentDictionary与Dictionary 替换
ConcurrentDictionary 与 Dictionary
ConcurrentDictionary与Dictionary