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

ConcurrentDictionary

.NET 锁定还是 ConcurrentDictionary?

ConcurrentDictionary和线程