免费下载案例集|20+数字化领先企业人才培养实践经验 了解详情
写点什么

构建更好的线程安全集合

  • 2009-02-26
  • 本文字数:1027 字

    阅读完需:约 3 分钟

大部分线程安全的集合都有一些基础性的缺陷:虽然每个操作都是线程安全的,但是多个操作无法组合起来使用。这意味着一些基本的执行顺序,例如在弹出顶部元素之前检查栈内元素数量会出现潜在的危险。尽管已经有一些 API 设法将某些操作绑定起来(例如.NET 4 的Coordination Data Structures ),但是它们往往会引入丑陋的方法(如TryDequeue)。

.NET 1 里的集合尝试了另一种方式,它们会对外暴露一个SyncRoot 属性,而不是在内部进行锁定。虽然SyncRoot 仍然是同步对象的默认机制,但是.NET 2 已经抛弃了SyncRoot/Wrapper 设计模式

那么该如何创建一个可用的组合式API 呢?Jared Parson 认为集合不应该直接暴露出线程安全的API,所有的方法都应该属于一个临时的对象,而这个对象只有在您锁定集合的时候才被创建出来。这个临时对象是集合的“钥匙”,只有钥匙的持有者才能获取集合内容。

以下示例为 Jared Parsons 的线程安全队列

复制代码
static void Example1(ThreadSafeQueue<int></int> queue) {<br></br> using (var locked = queue.Lock()) {<br></br> if (locked.Count > 0) {<br></br> var first = locked.Dequeue();<br></br> }<br></br> }<br></br>}

名为 locked 的对象本身不是线程安全的,但是开发人员只有在 using 代码块中才能正确执行操作。在遵守了这一简单规则之后,开发块里的所有代码就是线程安全的。Jared 解释道:

与大部分线程安全的设计一样,这些代码还是有被误用的可能:

  1. 在 ILockedQueue 销毁之后却继续使用它。这种做法应该被禁止,用户现有的知识一般足以避免这个问题。此外一些静态检查工具,例如 FxCop,会把这种做法识别为一个错误。我们也可以使用一种更严厉的做法来阻止此类情况出现:添加一个 disposed 标记,并在每个方法中进行检查。
  2. 如果用户在跨越多个 Lock 语句的情况下保留某个值(例如 Count),那么可能会对集合的状况出现错误的判断和假设。
  3. 如果用户没有正确销毁 ILockedQueue,那么这个对象会被永久锁定。幸运的是,对于实现了 IDisposable 的对象,FxCop 同样会将这种做法识别为一个错误——尽管这不是一个万分稳妥的机制。
  4. 无法确定用户是否会长期持有 ILockedQueue 对象。虽然 IDisposable 一般包含着“短期”的意味,但是这并不能做出完美的保证。
  5. ILockedQueue 并不是线程安全的。虽然一般情况下用户不会把 IDisposable 对象交给多个线程使用,但这也是必须考虑到的情况之一。

查看英文原文: Building a Better Thread-safe Collection

2009-02-26 06:281527
用户头像

发布了 157 篇内容, 共 54.4 次阅读, 收获喜欢 6 次。

关注

评论

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

当心这些“坑”!阿里云服务器部署前后端分离项目

麦洛

nginx 前后端分离 跨域

边缘计算,如何啃下集群管理这块硬骨头?

BoCloud博云

云计算 容器 边缘计算 PaaS 博云

Docker 容器编排利器 Docker Compose

哈喽沃德先生

Docker 容器 微服务 Docker-compose

大厂运维必备技能:PB级数据仓库性能调优

华为云开发者联盟

架构 数据

呕心沥血,整理200+最新面试题,面试之前看一下,事半功倍

小Q

Java 学习 程序员 架构 面试

[翻译]Go Concurrency Patterns[Go 并发模式]

卓丁

Rob Pike Go Concurrency Patterns Concurrency Go 语言

传统产业数字化转型的思考与建议

CECBC

经济转型 企业经济

物联网通信技术最全科普!你一定要了解的NB-IoT

华为云开发者联盟

物联网

协同新机遇:让研发敏捷起来

人称T客

合约跟单app,永续合约交易所带单交易软件

一步搞定任意圆角背景

mengxn

android xml 圆角

[翻译]The Go scheduler[Go调度]

卓丁

Go scheduler Go 语言

新基建夯实粤港澳大湾区高质量发展基础

CECBC

区块链 人工智能 大数据

去中心化交易所搭建,虚拟币去中心化交易系统

交易所开发

云图说 | GPU共享型AI容器,让AI开发更普及

华为云开发者联盟

AI 容器

Redis 哨兵模式

是老郭啊

redis redis哨兵模式 redis哨兵 redis哨兵集群

LeetCode题解:225. 用队列实现栈,两个队列,压入 -O(1), 弹出 -O(n),JavaScript,详细注释

Lee Chen

大前端 LeetCode

模板方法模式——看看 JDK 和 Spring 是如何优雅复用代码的

Java架构师迁哥

未读消息(小红点),前端与 RabbitMQ实时消息推送实践,贼简单~

程序员小富

Java RabbitMQ mqtt

indexOf原理,Java,javascript,python实现

叫练

算法

深度解析!--阿里开源分布式事务框架Seata

攀岩飞鱼

分布式 分布式事务 微服务 分布式锁 Seate

The Go Blog-Article index

卓丁

【万字长文】探讨可信构架之道

华为云开发者联盟

架构 服务端

MySQL高性能架构设计原则

洛神灬殇

教师节特别活动:第四范式多项自研技术及其应用实践分享

天枢数智运营

人工智能 推荐系统 第四范式 个性化推荐

使用开源软件构建工业互联网的平台

刘旭东

工业互联网 Odoo thingsboard

CSS常用样式——绘制单(双)箭头的多种方法(2)

程序员学院

CSS html 程序员

XSKY ClickHouse如何实现存算分离

XSKY星辰天合

Polkadot初识,不止于跨链

QTech

polkadot 跨链

20张图,大学四年都没整明白的操作系统就这么学会了

小Q

Java 程序员 架构 操作系统

未来经济 数字优先 | 大数据专场

腾讯云大数据

大数据

构建更好的线程安全集合_.NET_Jonathan Allen_InfoQ精选文章