本文导读: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# 代码   复制

public class Program

    {
static Dictionary<string, Logger> loggreDic;
static object loggerDicLocker = new object();
public static void Main()
{
loggreDic = new Dictionary<string, Logger>();
for (int i = 0; i < 100; i++)
{
ThreadPool.QueueUserWorkItem(o =>
{
try
{
var logger = GetLogger("AAA");
}
catch (Exception)
{
Console.WriteLine(string.Format("第{0}个线程出现问题", o));
}

}, i);
}
Console.ReadKey();
}

static Logger GetLogger(string cmdId)
{
if (!loggreDic.ContainsKey(cmdId))
{
loggreDic.Add(cmdId, LogManager.GetLogger(string.Format("AAA.{0}", cmdId)));
}
return loggreDic[cmdId];
}
}

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

解决方法

可以用ConcurrentDictionary 替代Dictionary

 
C# 代码   复制

    public interface IGetLogger

    {
Logger GetLogger(string cmdId);
}

public class ConcurrentDictionaryLogger : IGetLogger
{
ConcurrentDictionary<string, Logger> loggreDic = new ConcurrentDictionary<string, Logger>();
public Logger GetLogger(string cmdId)
{
if (!loggreDic.ContainsKey(cmdId))
{
loggreDic.TryAdd(cmdId, LogManager.GetLogger(string.Format("AAA.{0}", cmdId)));
}
return loggreDic[cmdId];
}
}

public static void Main()
{
IGetLogger conLogger = new ConcurrentDictionaryLogger();

IGetLogger lockerLogger = new LockerDictionaryLogger();

CodeTimer.Time("使用ConcurrentDictionary", 1000000, () =>
{
ThreadPool.QueueUserWorkItem(o =>
{
try
{
var logger = conLogger.GetLogger("AAA");
if (logger == null)
{
Console.WriteLine(string.Format("第{0}个线程获取到的值是 NULL", o));
}
}
catch (Exception ex)
{
Console.WriteLine(string.Format("第{0}个线程出现问题, {1}", o, ex.Message));
}
});
});
}

ConcurrentDictionary与Dictionary 替换的更多相关文章

  1. ConcurrentDictionary 与 Dictionary

    ASP.NET中ConcurrentDictionary是.Net4 增加的,与 Dictionary 最主要区别是, 前者是线程安全的集合,可以由多个线程同时并发读写Key-value.   那么 ...

  2. ConcurrentDictionary 对决 Dictionary+Locking

    在 .NET 4.0 之前,如果我们需要在多线程环境下使用 Dictionary 类,除了自己实现线程同步来保证线程安全之外,我们没有其他选择. 很多开发人员肯定都实现过类似的线程安全方案,可能是通过 ...

  3. 浅谈ConcurrentDictionary与Dictionary

    在.NET4.0之前,如果我们需要在多线程环境下使用Dictionary类,除了自己实现线程同步来保证线程安全外,我们没有其他选择.很多开发人员肯定都实现过类似的线程安全方案,可能是通过创建全新的线程 ...

  4. ConcurrentDictionary和Dictionary

    http://stackoverflow.com/questions/6739193/is-the-concurrentdictionary-thread-safe-to-the-point-that ...

  5. 用Dictionary替换switch case

    用switch case处理一个很长的判断,例如56个民族01代表汉族,02代表藏族,03代表壮族...,当传入数字想获取民族名称时就得写56个case,当传入民族获取背后的数字时,又得再写56个ca ...

  6. ConcurrentDictionary并发字典知多少?

    背景 在上一篇文章你真的了解字典吗?一文中我介绍了Hash Function和字典的工作的基本原理. 有网友在文章底部评论,说我的Remove和Add方法没有考虑线程安全问题. https://doc ...

  7. 改进ConcurrentDictionary并行使用的性能

    上一篇文章“ConcurrentDictionary 对决 Dictionary+Locking”中,我们知道了 .NET 4.0 中提供了线程安全的 ConcurrentDictionary< ...

  8. ConcurrentDictionary<TKey, TValue>的AddOrUpdate方法

    https://msdn.microsoft.com/zh-cn/library/ee378665(v=vs.110).aspx 此方法有一共有2个,现在只讨论其中一个 public TValue A ...

  9. 1、C#中Hashtable、Dictionary详解以及写入和读取对比

    在本文中将从基础角度讲解HashTable.Dictionary的构造和通过程序进行插入读取对比. 一:HashTable 1.HashTable是一种散列表,他内部维护很多对Key-Value键值对 ...

随机推荐

  1. jvm详情——5、选择合适的垃圾收集算法

    回收器选择JVM给了三种选择:串行收集器.并行收集器.并发收集器,但是串行收集器只适用于小数据量的情况,所以这里的选择主要针对并行收集器和并发收集器. 默认情况下,JDK5.0以前都是使用串行收集器, ...

  2. WebBrowser使用例子

    本文参考了:http://www.cnblogs.com/txw1958/archive/2012/09/24/CSharp-WebBrowser.html 在上文的基础上加入了 一些处理弹出对话框的 ...

  3. Docker 快速入门之 Dockerfile

    在 Docker 中我们可以从名为 Dockerfile 的文件中读取指令并且自动构建镜像.在本文中,将介绍 Dockerfile 的基本语法以及基本知识. Dockerfile 是什么 Docker ...

  4. c# 项目之间循环引用vs弹窗提醒

    circular dependencies in projects' graph ! Projects in cycle are:ProjectImp(Name:FrameWork.Entity,Pl ...

  5. SpringBoot中并发定时任务的实现、动态定时任务的实现(看这一篇就够了)

    原创不易,如需转载,请注明出处https://www.cnblogs.com/baixianlong/p/10659045.html,否则将追究法律责任!!! 一.在JAVA开发领域,目前可以通过以下 ...

  6. hive SQL查询结果添加行号

    用窗口函数可以解决这个问题: 例:select row_number() over(order by user_id desc) ,tab.* from dws_user_visit_month1 a ...

  7. 函数多个返回值与unpack的用法

    -- return the index of max number and himself -- 函数可以返回多个值 function get_max( T ) ] for i, v in ipair ...

  8. 远程过程调用概述-RMI简介

    简介: RPC是远程过程调用(Remote Procedure Call)的缩写形式.SAP系统RPC调用的原理其实很简单,有一些类似于三层构架的C/S系统,第三方的客户程序通过接口调用SAP内部的标 ...

  9. C# 任务 数据加载不影响其他操作

    private void button1_Click(object sender, EventArgs e) { //this.timer1.Enabled = true; Task t1 = new ...

  10. blfs(systemd版本)学习笔记-编译安装gnome桌面组件及应用

    我的邮箱地址:zytrenren@163.com欢迎大家交流学习纠错! blfs中的gnome项目地址:http://www.linuxfromscratch.org/blfs/view/stable ...