本文导读:ASP.NET中ConcurrentDictionary是.Net4 增加的,相对于Dictionary的线程安全的集合, ConcurrentDictionary可实现一个线程安全的集合,可以由多个线程同时并发读写Key-value,与Dictionary的区别主要有以下几点

一、Dictionary<TKey, TValue>

1、泛型类提供了从一组键到一组值的映射。通过键来检索值的速度是非常快的,这是因为 Dictionary<TKey,TValue> 类是作为一个哈希表来实现的。检索速度取决于为 TKey 指定的类型的哈希算法的质量。

2、TValue可以是值类型,数组,类或其他。

3、一个类的实例里,有个属性是个字典,我们不加考虑的会用Dictionary,而当这个属性被提升为static静态的(类级别的)时候,我们就要考虑它的线程安全性了,因为它有可能被多个线程同时访问,当然,如果这个对象是只读的,也无所谓线程安全,但如果这个属性是可以被写的,那就需要把它加锁了。

4、若允许多个线程对集合执行读写操作,您必须实现自己的同步,读写并行的时候需要加锁,但是加上锁性能就会受影响。

 

二、ConcurrentDictionary<TKey, TValue>

1、表示可由多个线程同时访问的键/值对的线程安全集合。

2、ConcurrentDictionary是.net4.0推出的一套线程安全集合里的其中一个,和它一起被发行的还有

ConcurrentStack,ConcurrentQueue等类型,它们的单线程版本(线程不安全的,Queue,Stack,Dictionary)。

3、用法同Dictionary很多相同,但是多了一些方法。ConcurrentDictionary 属于System.Collections.Concurrent 命名空间

 

三、ConcurrentDictionary与Dictionary的区别实例

 

在多线程环境下,下面实例判断Key是否存

 

 
C# 代码   复制
ConcurrentDictionary与Dictionary 替换ConcurrentDictionary与Dictionary 替换
public class Program
{ ConcurrentDictionary与Dictionary 替换 static Dictionary<string, Logger> loggreDic; ConcurrentDictionary与Dictionary 替换 static object loggerDicLocker = new object(); ConcurrentDictionary与Dictionary 替换 public static void Main() { ConcurrentDictionary与Dictionary 替换 loggreDic = new Dictionary<string, Logger>(); ConcurrentDictionary与Dictionary 替换 for (int i = 0; i < 100; i++) { ConcurrentDictionary与Dictionary 替换 ThreadPool.QueueUserWorkItem(o => { ConcurrentDictionary与Dictionary 替换 try { ConcurrentDictionary与Dictionary 替换 var logger = GetLogger("AAA"); ConcurrentDictionary与Dictionary 替换 } ConcurrentDictionary与Dictionary 替换 catch (Exception) { ConcurrentDictionary与Dictionary 替换 Console.WriteLine(string.Format("第{0}个线程出现问题", o)); ConcurrentDictionary与Dictionary 替换 } ConcurrentDictionary与Dictionary 替换ConcurrentDictionary与Dictionary 替换 }, i); ConcurrentDictionary与Dictionary 替换 } ConcurrentDictionary与Dictionary 替换 Console.ReadKey(); ConcurrentDictionary与Dictionary 替换 } ConcurrentDictionary与Dictionary 替换ConcurrentDictionary与Dictionary 替换 static Logger GetLogger(string cmdId) { ConcurrentDictionary与Dictionary 替换 if (!loggreDic.ContainsKey(cmdId)) { ConcurrentDictionary与Dictionary 替换 loggreDic.Add(cmdId, LogManager.GetLogger(string.Format("AAA.{0}", cmdId))); ConcurrentDictionary与Dictionary 替换 } ConcurrentDictionary与Dictionary 替换 return loggreDic[cmdId]; ConcurrentDictionary与Dictionary 替换 } ConcurrentDictionary与Dictionary 替换 } ConcurrentDictionary与Dictionary 替换

在GetLogger的地方做了判断的处理,但是在多线程的时候还是会报 已添加了具有相同键的项 的错误。原因是在Dictionary中加了重复的Key造成的。

 

解决方法

可以用ConcurrentDictionary 替代Dictionary

 

 
C# 代码   复制
ConcurrentDictionary与Dictionary 替换ConcurrentDictionary与Dictionary 替换
    public interface IGetLogger
{ ConcurrentDictionary与Dictionary 替换 Logger GetLogger(string cmdId); ConcurrentDictionary与Dictionary 替换 } ConcurrentDictionary与Dictionary 替换ConcurrentDictionary与Dictionary 替换 public class ConcurrentDictionaryLogger : IGetLogger { ConcurrentDictionary与Dictionary 替换 ConcurrentDictionary<string, Logger> loggreDic = new ConcurrentDictionary<string, Logger>(); ConcurrentDictionary与Dictionary 替换 public Logger GetLogger(string cmdId) { ConcurrentDictionary与Dictionary 替换 if (!loggreDic.ContainsKey(cmdId)) { ConcurrentDictionary与Dictionary 替换 loggreDic.TryAdd(cmdId, LogManager.GetLogger(string.Format("AAA.{0}", cmdId))); ConcurrentDictionary与Dictionary 替换 } ConcurrentDictionary与Dictionary 替换 return loggreDic[cmdId]; ConcurrentDictionary与Dictionary 替换 } ConcurrentDictionary与Dictionary 替换 } ConcurrentDictionary与Dictionary 替换ConcurrentDictionary与Dictionary 替换 public static void Main() { ConcurrentDictionary与Dictionary 替换 IGetLogger conLogger = new ConcurrentDictionaryLogger(); ConcurrentDictionary与Dictionary 替换ConcurrentDictionary与Dictionary 替换 IGetLogger lockerLogger = new LockerDictionaryLogger(); ConcurrentDictionary与Dictionary 替换ConcurrentDictionary与Dictionary 替换 CodeTimer.Time("使用ConcurrentDictionary", 1000000, () => { ConcurrentDictionary与Dictionary 替换 ThreadPool.QueueUserWorkItem(o => { ConcurrentDictionary与Dictionary 替换 try { ConcurrentDictionary与Dictionary 替换 var logger = conLogger.GetLogger("AAA"); ConcurrentDictionary与Dictionary 替换 if (logger == null) { ConcurrentDictionary与Dictionary 替换 Console.WriteLine(string.Format("{0}个线程获取到的值是 NULL", o)); ConcurrentDictionary与Dictionary 替换 } ConcurrentDictionary与Dictionary 替换 } ConcurrentDictionary与Dictionary 替换 catch (Exception ex) { ConcurrentDictionary与Dictionary 替换 Console.WriteLine(string.Format("第{0}个线程出现问题, {1}", o, ex.Message)); ConcurrentDictionary与Dictionary 替换 } ConcurrentDictionary与Dictionary 替换 }); ConcurrentDictionary与Dictionary 替换 }); ConcurrentDictionary与Dictionary 替换 }

相关文章:

  • 2022-01-02
  • 2022-01-01
  • 2022-12-23
  • 2021-08-24
  • 2021-06-27
  • 2021-12-04
猜你喜欢
  • 2022-02-23
  • 2022-12-23
  • 2022-01-19
  • 2022-12-23
  • 2021-10-26
  • 2022-12-23
相关资源
相似解决方案