写点什么

构建更好的线程安全集合

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

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

关注

评论

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

什么是数据产品经理?数据产品经理与传统产品经理有什么区别?

雨果

数据产品经理

【从0到1学算法】5.Bubble Sort算法-下

Geek_65222d

10月月更

cstdio的源码学习分析10-格式化输入输出函数fprintf---宏定义/辅助函数分析03

桑榆

源码刨析 10月月更 C++

「趣学前端」容器上的折角边框是图形吗?

叶一一

CSS 前端 10月月更

一文搞懂常见的网络I/O模型

闫同学

网络 网络io 10月月更

挑战30天学完 Python:Day4数据类型-字符串str

MegaQi

挑战30天学完Python 10月月更

【LeetCode】两个链表的第一个重合节点Java题解

Albert

算法 LeetCode 10月月更

有人意图取代SQL,你同意吗?

雨果

sql

「趣学前端」日常浏览的页面为什么可以五颜六色

叶一一

CSS 前端 10月月更

趣学前端」为什么有的页面背景颜色是渐变的

叶一一

CSS 前端 10月月更

一个实际的例子学习 SAP BTP Java 应用的 @Before 注解使用方式

汪子熙

Java 云原生 Cloud SAP 10月月更

测试需求平台5-Blueprint优化与首个vue页搭建

MegaQi

测试平台开发教程 10月月更

大数据ELK(二十六):探索数据(Discovery)

Lansonli

discovery 10月月更

Go-Excelize API源码阅读(二十二)——SetAppProps(appProperties *AppProperties)

Regan Yue

Go 开源 源码分析 Excelize 10月月更

正在消失的机器视觉公司

脑极体

面试官:说说你对Node中的Stream的理解

CoderBin

面试 前端 Node 10月月更

Go-Excelize API源码阅读(二十一)——GetDefinedName()、DeleteDefinedName()

Regan Yue

Go 源码阅读 源码刨析 10月月更

Serverless的应用场景

阿泽🧸

Serverless 10月月更

「趣学前端」box-shadow的多重用法

叶一一

CSS 前端 10月月更

首轮Zepoch节点已售罄完结,你期待次轮吗?

鳄鱼视界

前端开发提效小技巧之业务功能篇

叶一一

前端 提高效率 10月月更

浅谈etcd服务注册与发现

闫同学

Go 微服务 etcd 10月月更

【一Go到底】第十五天---continue快速入门

指剑

Go golang 10月月更

Python进阶(二十三)Django使用pymysql连接MySQL数据库做增删改查

No Silver Bullet

Python django MySQL数据库 pymysql 10月月更

Java三大特性(一)—封装

共饮一杯无

Java 面向对象 10月月更

华为云从入门到实战 | 负载均衡服务原理

TiAmo

华为 云开发 10月月更

Go-Excelize API源码阅读(二十三)——SetDocProps、GetDocProps

Regan Yue

Go 开源 源码刨析 10月月更

Python进阶(二十二)Python3使用PyMysql连接mysql数据库

No Silver Bullet

Python3 MySQL数据库 pymysql 10月月更

B类纯资金业务的资金安全保障

agnostic

资金安全 B类业务 纯资金业务

「趣学前端」页面上吸顶的效果是怎么做到的

叶一一

CSS 前端 10月月更

如何在高性能的前提下,降低数据库存储成本?

OceanBase 数据库

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