在 2025 收官前,看清 Data + AI 的真实走向,点击查看 BUILD 大会精华版 了解详情
写点什么

构建更好的线程安全集合

  • 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:282038
用户头像

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

关注

评论

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

抽奖小助手——利益相关者

墨狂之逸才

面试官:你说说ReentrantLock和Synchronized区别

叫练

AQS 多线程 ReentrantLock lock 独占锁

MapReduce练习案例1-统计求和

小马哥

大数据 mapreduce 七日更

Mybatis系列全解(二):Mybatis简介与环境搭建

潘大壮

Java 后端 mybatis mybatis源码

Java 程序经验小结:反射机制勿滥用

后台技术汇

28天写作

70 张图带你彻底掌握红黑树

Java 数据结构 红黑树

融资融券系统搭建

v16629866266

实习流水帐(一)

YUKI0506

面试学习!我们究竟还要学习哪些Android知识?讲的明明白白!

欢喜学安卓

android 程序员 面试 移动开发

anyRTC在音频领域的探索

anyRTC开发者

ios android 音视频 WebRTC 在线教育

Spring 是如何解决循环依赖的?

程序员小航

Java spring 源码 循环依赖

Mybatis系列全解(三):Mybatis简单CRUD使用介绍

潘大壮

Java 后端 mybatis mybatis源码

一看就懂的网络传输介质介绍

面试加分项!Android项目开发如何设计整体架构?学习路线+知识点梳理

欢喜学安卓

android 程序员 面试 移动开发

第二章作业

白知之明

「Android渲染」图像是怎样显示到屏幕上的?

李小四

Android渲染 AndroidUI RenderingPipeline

产品经理训练营 - 第二周作业

泡面加煎蛋

产品经理训练营 - 第二章作业

Ryun

拆解 抽奖助手 的利益相关者

小匚

产品经理 产品经理训练营 无码科技

产品经理的大局观——

小匚

产品经理 产品经理训练营

阿里开始“拆”中台?!中台建设何去何从?

博文视点Broadview

作业:挑一个你喜欢的产品平台,列出产品的利益相关方。

嫉妒的耗子

阿里发布2021年Redis“神级”手册:基础+原理+应用+集群+拓展+源码,六管齐下

Java架构追梦

Java redis 阿里巴巴 源码 架构

CNCF CTO解读:2021云原生最新趋势

华为云原生团队

开源 Kubernetes 开发者 云原生 边缘技术

Mybatis系列全解(一):手写一套持久层框架

潘大壮

Java 后端 mybatis mybatis源码

产品训练营-第二周-作业

邹小胖

产品经理训练营

Springboot使用jasypt需要注意的一个小地方

Sky彬

springboot jasypt

产品训练营 - 对二次作业

Wangyunnfei

Mybatis系列全解(五):全网最全!详解Mybatis的Mapper映射文件

潘大壮

Java 后端 mybatis mybatis源码

产品经理第二周作业

朱琴

Mybatis系列全解(四):全网最全!Mybatis配置文件XML全貌详解

潘大壮

Java 后端 mybatis mybatis源码

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