c++ - memory_order_acquire 对可简单破坏的类型的引用计数指针是否是多余的?
问题描述
这个问题专门针对引用计数指针中的可简单破坏的类型。请参阅Boost 文档中有关原子使用的示例。
减量如下:
if (x->refcount_.fetch_sub(1, boost::memory_order_release) == 1) {
// A
boost::atomic_thread_fence(boost::memory_order_acquire);
delete x;
}
我们知道,由于
memory_order_release
,所有的读/写x
都在fetch_sub
(见这里)之前完成。因此,如果我们碰巧到达了点,A
那么所有的使用x
都是完整的。在
A
代码中,标准不能保证我们看到栅栏x
之后的最新值......memory_order_acquire
所以这是我关于第二个陈述的问题memory_order_acquire
:
什么时候x
指向一个可简单破坏的类型(例如int
where x
is int * const
)是memory_order_acquire
没有意义的?我的理由是因为如果x
是微不足道的破坏那么最新的更改x
不会影响删除x
?
例如,删除线程是否delete x;
看到最新x
的*x = 10
值或过时的值,以便*x = 8
销毁过程始终相同(只要指针x
本身保持不变)。它知道没有人会x
因为发布而从那时起修改它,因此它所要做的就是解除分配。
memory_order_acquire
我在这里想念的还有另一个好处吗?我的想法是否正确,如果不是,那么为什么我们需要查看x
删除线程上的最新值?
解决方案
让我们考虑以下示例:
初始化
int * const x = new int{42};
std::atomic<int> refcount = 2;
线程A和线程B
assert(*x == 42);
if (refcount.fetch_sub(1, std::memory_order_release) == 1) {
// std::atomic_thread_fence(std::memory_order_acquire);
delete x;
}
在该示例中,断言可能会失败或更糟,因为它可以访问已经销毁和释放的对象。问题是在一个线程中的访问和另一个线程中的删除之间没有发生关系。即使在使用时*x
,断言也可以在同一线程中递减后重新排序。refcount
memory_order_release
为了在关系之前形成这种情况,我们需要线程之间的同步点,而release-acquire正是这样做的。这就是为什么我们需要在删除之前获取栅栏*x
。或者,我们可以在递减时使用memory_order_acq_rel
而不是,这也足够了。memory_order_release
refcount
推荐阅读
- excel - OLAP 过滤层次混淆
- php - 将 root 用户名更改为 dlb123 但可以访问 mysql 时 phpMyAdmin 出现 4r03 错误
- html - 无法从默认包中的 servlet 调用 WEB-INF 中的 jsp
- javascript - Javascript 相关问题(运算符和优先级)
- javascript - 计算每 12 个计数的值
- reactjs - 类型“[{},Dispatch<{}>]”缺少类型中的以下属性
- java - 为什么在将我的 java 程序连接到 sql server 时出现此错误
- r - 在R中选择只有一个字符的列
- powershell - 基于注释的帮助不显示 .NOTES 部分中的内容
- php - 为什么不同日期的日期和时间转换不同?