[论文解读] Concurrent Reference Counting and Resource Management in Wait-free Constant Time
本文提出了一种无锁、无等待的并发引用计数机制,采用获取-退役接口,确保常数时间开销和有界空间的资源管理。通过利用单字形单元原子操作和四条原语接口(获取、释放、退役、弹出),实现了高效、无数据竞争的内存与资源回收,且在多种工作负载下具有期望的 O(1) 性能,优于现有基于锁和无锁的替代方案,尤其在高竞争场景下表现更优。
A common problem when implementing concurrent programs is efficiently protecting against unsafe races between processes reading and then using a resource (e.g., memory blocks, file descriptors, or network connections) and other processes that are concurrently overwriting and then destructing the same resource. Such read-destruct races can be protected with locks, or with lock-free solutions such as hazard-pointers or read-copy-update (RCU). In this paper we describe a method for protecting read-destruct races with expected constant time overhead, $O(P^2)$ space and $O(P^2)$ delayed destructs, and with just single word atomic memory operations (reads, writes, and CAS). It is based on an interface with four primitives, an acquire-release pair to protect accesses, and a retire-eject pair to delay the destruct until it is safe. We refer to this as the acquire-retire interface. Using the acquire-retire interface, we develop simple implementations for three common use cases: (1) memory reclamation with applications to stacks and queues, (2) reference counted objects, and (3) objects manage by ownership with moves, copies, and destructs. The first two results significantly improve on previous results, and the third application is original. Importantly, all operations have expected constant time overhead.
研究动机与目标
- 解决并发系统中读-销毁竞争问题,即多个线程可能同时访问或销毁共享资源。
- 设计一种无锁、无等待的资源管理机制,确保及时销毁资源,避免锁带来的性能瓶颈。
- 通过支持每个资源的多次退役操作以及复制-销毁接口,推广现有内存回收技术,提升适用范围。
- 在仅使用单字形单元原子操作(CAS、读取、写入)的前提下,实现每项操作的常数时间开销,同时保持有界空间。
- 评估所提接口在真实工作负载下的性能表现,特别是在高竞争和不同存储频率条件下的表现。
提出的方法
- 本文引入获取-退役接口,包含四种原语:获取(安全读取资源句柄)、释放(释放保护)、退役(将资源标记为过时)、弹出(在所有读者完成访问后安全销毁资源)。
- 该方法为每个线程使用本地哈希表管理退役-弹出对,即使存在竞争,也能实现期望的常数时间操作。
- 在获取操作中采用快路径/慢路径优化策略,先尝试无锁版本,失败后回退至无等待变体。
- 引入 weak_atomic 模板,用于包装任意具有复制和析构语义的类型,实现对任意类型的安全并发引用计数。
- 系统使用 C++ 实现,基于原子原语,并与标准实现(如 std::shared_ptr)及 just::thread 的 atomic_shared_ptr 进行对比评估。
- 系统保证线性化,即所有操作均表现为原子操作,并支持同一资源上多个并发的退役-弹出对。
实验结果
研究问题
- RQ1一个并发资源管理系统是否能在不依赖锁的前提下,实现访问和销毁操作的期望常数时间开销?
- RQ2与现有的无锁技术(如危险指针和 RCU)相比,所提出的获取-退役接口在性能和空间效率方面表现如何?
- RQ3该接口是否支持对同一资源的多次退役操作,从而实现高效的引用计数和对象所有权转移?
- RQ4在频繁存储和共享指针更新的高竞争工作负载下,该接口的性能扩展特性如何?
- RQ5该接口在多大程度上可泛化以支持除内存块外的任意具有复制和析构语义的类型?
主要发现
- 在给定假设下,所提出的获取-退役接口对所有操作(包括获取、释放、退役、弹出)均实现了期望的 O(1) 时间复杂度。
- 在低竞争工作负载(N=10M)下,两种实现——Weak Atomic std::shared_ptr 和 Weak Atomic Custom shared_ptr——均实现了近乎完美的可扩展性,32 核环境下加速比达到 30–31 倍。
- 在高竞争工作负载(N=10)下,两种实现仍表现出适度但稳定的可扩展性,单核性能和吞吐量均优于 GNU C++ 库的基于锁实现以及 just::thread 的无锁实现。
- 在低竞争、高负载场景下,just::thread 库表现更优,但在存储密集型工作负载中,其单核性能相比本方法慢了 8 倍以上。
- GNU C++ 库的实现由于全局锁竞争,尽管单核性能与本方法相近,但在 32 核环境下仅实现了 3 倍加速。
- weak_atomic 抽象实现了干净、可重用的并发引用计数实现,支持具有复制和析构语义的任意类型,充分体现了该框架的通用性与实用性。
更好的研究,从现在开始
从阅读论文到最终审阅,大幅缩短您的研究时间。
无需绑定信用卡
本解读由 AI 生成,并经人工编辑审核。