zoukankan      html  css  js  c++  java
  • 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();
            }
    
    
        }
    会有一定几率出现异常情况:
     
     
     
     
     
     
     
     
     
     
     
     
     
     
     
     
  • 相关阅读:
    创建react项目
    解决移动端弹窗下页面滚动问题
    前端常用的几种加密方式
    http请求状态码
    vue代理配置
    自动化测试实操案例详解 | Windows应用篇
    Google 再见 Java
    一次诡异的 SQL 数量统计查询不准的问题
    Maven
    淘宝技术分享:手淘亿级移动端接入层网关的技术演进之路
  • 原文地址:https://www.cnblogs.com/dragon-L/p/8442655.html
Copyright © 2011-2022 走看看