当前位置:  开发笔记 > 编程语言 > 正文

完全线程安全的shared_ptr实现

如何解决《完全线程安全的shared_ptr实现》经验,为你挑选了1个好方法。

有人知道完全线程安全的shared_ptr实现吗?例如,boost实现shared_ptr对于目标(引用计数)是线程安全的,并且对于同时shared_ptr实例读取也是安全的,但不是写入或读/写.

(参见Boost docs,例3,4和5).

是否存在对shared_ptr实例完全线程安全的shared_ptr实现?

提升文档的人说:

shared_ptr对象提供与内置类型相同的线程安全级别.

但是如果你比较一个普通的指针(内置类型)smart_ptr,那么同时写一个普通的指针是线程安全的,但同时写入a smart_ptr不是.

编辑:我的意思是x86架构上的无锁实现.

EDIT2:这种智能指针的一个示例用例是有许多工作线程,它们使用当前工作项更新全局shared_ptr,并使用监视器线程获取工作项的随机样本.shared-ptr将拥有该工作项,直到为其分配了另一个工作项指针(从而销毁了以前的工作项).监视器将获得工作项的所有权(从而防止工作项被销毁),方法是将其分配给自己的shared-ptr.它可以通过XCHG和手动删除来完成,但如果共享ptr可以做到这一点会很好.

另一个例子是全局shared-ptr拥有"处理器",由某个线程分配,并由其他一些线程使用.当"用户"线程看到处理器shard-ptr为NULL时,它使用一些替代逻辑来进行处理.如果它不是NULL,它会通过将处理器分配给它自己的shared-ptr来防止处理器被破坏.



1> bdonlan..:

为这种完全线程安全的shared_ptr实现添加必要的障碍可能会影响性能.考虑下面的比赛(注意:伪代码比比皆是):

线程1:global_ptr = A;

线程2:global_ptr = B;

线程3:local_ptr = global_ptr;

如果我们将其分解为其组成操作:

线程1:

A.refcnt++;
tmp_ptr = exchange(global_ptr, A);
if (!--tmp_ptr.refcnt) delete tmp_ptr;

线程2:

B.refcnt++;
tmp_ptr = exchange(global_ptr, B);
if (!--tmp_ptr.refcnt) delete tmp_ptr;

线程3:

local_ptr = global_ptr;
local_ptr.refcnt++;

显然,如果线程3在A的交换之后读取指针,那么B会在引用计数递增之前删除它,会发生不好的事情.

为了解决这个问题,我们需要在线程3进行refcnt更新时使用虚拟值:(注意:compare_exchange(variable,expected,new)原子地将变量中的值替换为new,如果它当前等于new,则返回true如果成功的话)

线程1:

A.refcnt++;
tmp_ptr = global_ptr;
while (tmp_ptr == BAD_PTR || !compare_exchange(global_ptr, tmp_ptr, A))
    tmp_ptr = global_ptr;
if (!--tmp_ptr.refcnt) delete tmp_ptr;

线程2:

B.refcnt++;
while (tmp_ptr == BAD_PTR || !compare_exchange(global_ptr, tmp_ptr, A))
    tmp_ptr = global_ptr;
if (!--tmp_ptr.refcnt) delete tmp_ptr;

线程3:

tmp_ptr = global_ptr;
while (tmp_ptr == BAD_PTR || !compare_exchange(global_ptr, tmp_ptr, BAD_PTR))
    tmp_ptr = global_ptr;
local_ptr = tmp_ptr;
local_ptr.refcnt++;
global_ptr = tmp_ptr;

你现在必须在/ read/operation中间添加一个循环,其中包含atomics.这不是一件好事 - 在一些CPU上它可能非常昂贵.更重要的是,你也在忙着等待.你可以开始聪明地使用futexes等等 - 但是到那时你已经重新发明了锁.

这个成本必须由每个操作承担,并且在本质上与锁给你的方式非常相似,这就是为什么你通常看不到这样的线程安全的shared_ptr实现.如果您需要这样的东西,我建议将mutex和shared_ptr包装到一个便捷类中以自动锁定.

推荐阅读
linjiabin43
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有