gpt4 book ai didi

c++ - 将全局引用计数资源与原子同步——在这里放宽合适吗?

转载 作者:行者123 更新时间:2023-12-05 08:24:50 26 4
gpt4 key购买 nike

我有一个全局引用计数对象obj,我想通过使用原子操作来防止数据竞争:

T* obj;                  // initially nullptr
std::atomic<int> count; // initially zero

我的理解是,我需要在写入obj 后使用std::memory_order_release,以便其他线程知道它正在创建:

void increment()
{
if (count.load(std::memory_order_relaxed) == 0)
obj = std::make_unique<T>();

count.fetch_add(1, std::memory_order_release);
}

同样,我需要在读取计数器时使用std::memory_order_acquire,以确保线程可以看到正在更改的obj:

void decrement()
{
count.fetch_sub(1, std::memory_order_relaxed);

if (count.load(std::memory_order_acquire) == 0)
obj.reset();
}

我不相信上面的代码是正确的,但我也不完全确定为什么。我觉得在 obj.reset() 被调用之后,应该有一个 std::memory_order_release 操作来通知其他线程。对吗?

是否还有其他可能出错的地方,或者我对这种情况下的原子操作的理解完全错误?

最佳答案

不管内存顺序如何都是错误的。

正如@MaartenBamelis 指出的increment 的并发调用,对象被构建了两次。并发 decrement 也是如此:对象被重置两次(这可能导致两次析构函数调用)。

请注意,在 T* obj; 声明和将其用作 unique_ptr 之间存在分歧,但是原始指针和唯一指针对于并发修改都是不安全的。实际上,resetdelete 将检查指针是否为空,然后删除并将其设置为空,这些步骤不是原子的。

fetch_addfetch_sub 是 fetch 和 op 而不仅仅是 op 是有原因的:如果你不使用操作过程中观察到的值,它很可能是一个种族。

关于c++ - 将全局引用计数资源与原子同步——在这里放宽合适吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/71129379/

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