gpt4 book ai didi

c++ - memory_order_relaxed 如何在智能指针中增加原子引用计数?

转载 作者:IT老高 更新时间:2023-10-28 23:18:45 34 4
gpt4 key购买 nike

考虑以下摘自 Herb Sutter 关于原子的演讲的代码片段:

smart_ptr 类包含一个名为 control_block_ptr 的 pimpl 对象,其中包含引用计数 refs

// Thread A:
// smart_ptr copy ctor
smart_ptr(const smart_ptr& other) {
...
control_block_ptr = other->control_block_ptr;
control_block_ptr->refs.fetch_add(1, memory_order_relaxed);
...
}

// Thread D:
// smart_ptr destructor
~smart_ptr() {
if (control_block_ptr->refs.fetch_sub(1, memory_order_acq_rel) == 1) {
delete control_block_ptr;
}
}

Herb Sutter 说线程 A 中 refs 的增量可以使用 memory_order_relaxed,因为“没有人根据 Action 做任何事情”。现在,据我了解 memory_order_relaxed,如果 refs 在某个时候等于 N,并且两个线程 A 和 B 执行以下代码:

control_block_ptr->refs.fetch_add(1, memory_order_relaxed);

那么可能会发生两个线程都看到 refs 的值为 N 并且都将 N+1 写回它的情况。这显然行不通,应该像使用析构函数一样使用 memory_order_acq_rel。我哪里错了?

EDIT1:考虑以下代码。

atomic_int refs = N; // at time t0. 

// [Thread 1]
refs.fetch_add(1, memory_order_relaxed); // at time t1.

// [Thread 2]
n = refs.load(memory_order_relaxed); // starting at time t2 > t1
refs.fetch_add(1, memory_order_relaxed);
n = refs.load(memory_order_relaxed);

在调用 fetch_add 之前,线程 2 观察到的 refs 的值是多少?可以是 N 还是 N+1?调用 fetch_add 后线程 2 观察到的 refs 的值是多少?必须至少是 N+2 吗?

[谈话网址:C++ & Beyond 2012 - http://channel9.msdn.com/Shows/Going+Deep/Cpp-and-Beyond-2012-Herb-Sutter-atomic-Weapons-2-of-2 (@ 1:20:00)]

最佳答案

模拟 std::atomic 的 Boost.Atomic 库提供 similar reference counting example and explanation ,这可能有助于您的理解。

Increasing the reference counter can always be done with memory_order_relaxed: New references to an object can only be formed from an existing reference, and passing an existing reference from one thread to another must already provide any required synchronization.

It is important to enforce any possible access to the object in one thread (through an existing reference) to happen before deleting the object in a different thread. This is achieved by a "release" operation after dropping a reference (any access to the object through this reference must obviously happened before), and an "acquire" operation before deleting the object.

It would be possible to use memory_order_acq_rel for the fetch_sub operation, but this results in unneeded "acquire" operations when the reference counter does not yet reach zero and may impose a performance penalty.

关于c++ - memory_order_relaxed 如何在智能指针中增加原子引用计数?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27631173/

34 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com