QCon北京「鸿蒙专场」火热来袭!即刻报名,与创新同行~ 了解详情
写点什么

ConcurrentDictionary:.NET 4.0 中新的线程安全的哈希表

  • 2010-01-31
  • 本文字数:1028 字

    阅读完需:约 3 分钟

ConcurrentDictionary 是.NET 4.0 中在并行和并发编程方面显著增强的基石。但是在对其进行深入研究之前,让我们来回顾一下在.NET 之前版本中存在的问题。

.NET 中哈希表的第一个版本是 System.Collections.Hashtable。尽管它并非是线程安全的,但在理论上你可以通过简单地调用 Hashtable.Synchronized 来得到线程安全的封装器。不幸的是,由于这个封装器所使用的方式,它并不是真正线程安全的,

比方说,你想要检查一个键值是否存在于集合中。如果不存在,那么你就想要执行一个不会重复的操作,在那里会将结果保存。即使 ContainsKey 和 set_Item 二者都分别是线程安全的,也没有一种方式能够直接对它们进行组合。作为替代的方法,你需要采用 SyncRoot 上的锁,这会推翻你在前面请求同步版本的所有理由。

当.NET 2.0 引入泛型和 System.Collections.Generic.Dictionary 的时候,微软还是没有解决这个问题。开发者需要采用自己的显式的锁。

.NET 3.5 没有添加任何技术,但是它确实使得我们更易于实现在函数式编程方面增强的程序。首先,它取消了定义自定义委托的思想。从那开始,在任何设计得足够好的 API 上,都可以重用泛型的 Action 和 Func 的委托。另一个优势是将 lambda 表达式引入到 VB 中,并且显著提升了它在 C#中的表现。结果是,使用这个 API,开发者可以很容易地像这样来创建他们自己的同步封装器:

复制代码
public TValue GetOrAdd(TKey key, Func<TKey, TValue> valueFactory)

在之前的版本中,开发者需要对锁进行操作,与此不同的是,在新的 ConcurrentDictionary 类中的这个方法看起来很容易就可以正确使用。我们只需要简单地提供一个键值和一个委托,如果键值不存在就会执行委托。由于函数本身是线程安全的,因此一切都应该是原子级的。

好吧,就算不是。为了“避免在锁之下执行未知的代码而引发的各种问题”,valueFactory 委托没有在锁中执行。因此就可能存在竞争条件,开发者需要确保 valueFactory 委托只执行可重复的操作。

如果你需要这项功能,那么你需要将 ConcurrentDictionary 类和 Lazy 类组合。这样做的示例代码包含在 AsyncCache 类中,它也作为示例被发布了。

尽管这个功能随时都会改变,但当前 ConcurrentDictionary 的实现已经带有不用锁的读取了。为了提升性能,开发者可以提供写线程的估计数目。这会控制着哈希表将使用多少细粒度的锁。

你可以从 Stephen Toub 的博客中学到更多关于ConcurrentDictionary 的知识

查看英文原文: ConcurrentDictionary, .NET 4.0’s New Thread-Safe Hashtable

2010-01-31 18:078703
用户头像

发布了 340 篇内容, 共 134.5 次阅读, 收获喜欢 13 次。

关注

评论

发布
暂无评论
发现更多内容

密码学系列之:memory-bound函数

程序那些事

加密解密 密码学 程序那些事

【Flutter 专题】87 初识状态管理 Bloc (二)

阿策小和尚

Flutter 小菜 0 基础学习 Flutter Android 小菜鸟 7月日更

【源码篇】Flutter GetX深度剖析 | 我们终将走出自己的路(万字图文)

小呆呆666

flutter ios android 大前端

ReactNative进阶(十六):React-Native 组件生命周期

No Silver Bullet

生命周期 React Native 组件 7月日更

详解SQL优化必备:并行执行框架和执行计划

华为云开发者联盟

sql SQL优化 执行计划 GaussDB(for openGauss) 并行执行框架

HarmonyOS开发者创新大赛作品《智能农场》相关开发技术分享

科技汇

颠覆传统经营模式,区块链助力餐饮行业数字化革新

旺链科技

数字化 区块链技术 餐饮

我是一个请求,我是如何被发送的?

华为云开发者联盟

注解 流程 CSE 请求 RestTemplat

机器学习

i30M

WATT NETWORK软件系统开发详情

禧大福酒口感怎么样?好喝又养生

Geek_50a546

【技术实践】基于Cglib动态代理,实现Spring的AOP核心功能!

小傅哥

spring 小傅哥 aop 动态代理 cglib

决定中国SaaS成败的三个关键问题

ToB行业头条

SaaS

MySQL事务分析

卢卡多多

事务 事务隔离 7月日更

Linux之chmod命令

入门小站

Linux

用mysql模拟实现消息队列

白发青年

#架构实战营

在线IEEE浮点二进制计算器工具

入门小站

工具

质量基础设施一站式服务平台建设,NQI平台解决方案

模块八:设计消息队列存储消息数据的 MySQL 表格

ifc177

Vue进阶(四十五):精解ES6 Promise 用法

No Silver Bullet

Vue Promise 异步编程 7月日更

模块二作业-微信朋友圈复杂度分析

babos

#架构实战营

自建开发工具系列-Webkit内存动量监控UI(五)

Tim

typescript js 转 ts tsx tsconfig

【LeetCode】二叉树的层序遍历Java题解

Albert

算法 LeetCode 7月日更

价值连城 杰弗里·欣顿(Geoffrey·Hinton)的采访 给AI从业者的建议 John 易筋 ARTS 打卡 Week 55

John(易筋)

ARTS 打卡计划

快速构建JVM整体认知-JVM的生命周期

刘绍

Java 程序员 JVM JVM原理 规范

新手程序员必备10大技能

禅道项目管理

Linux 程序员 语言 git 学习

“攻城狮”实用指南之Linux CPU性能优化

中原银行

Linux

Rust从0到1-智能指针-内存泄漏

rust 智能指针 内存泄漏 循环引用 smart pointer

设计消息队列存储消息数据的 MySQL 表结构

贯通

架构实战营

毕业四年,我当初是如何走上编程这条路的!

Andy阿辉

程序员 开发 大学生 编程故事 自我成长

Scrapy 爬取西刺代理存入MySQL & MongoDB 数据库(手把手教学,超详细步骤)

若尘

MySQL mongodb 爬虫 Scrapy 7月日更

ConcurrentDictionary:.NET 4.0中新的线程安全的哈希表_.NET_Jonathan Allen_InfoQ精选文章