gpt4 book ai didi

c++ - 引用计数线程安全吗

转载 作者:太空狗 更新时间:2023-10-29 23:20:32 25 4
gpt4 key购买 nike

例如考虑

class ProcessList {
private
std::vector<std::shared_ptr<SomeObject>> list;
Mutex mutex;
public:
void Add(std::shared_ptr<SomeObject> o) {
Locker locker(&mutex); // Start of critical section. Locker release so will the mutex - In house stuff
list.push_back(std::make_shared<SomeObject>(o).
}

void Remove(std::shared_ptr<SomeObject> o) {
Locker locker(&mutex); // Start of critical section. Locker release so will the mutex - In house stuff
// Code to remove said object but indirectly modifying the reference count in copy below
}

void Process() {
std::vector<std::shared_ptr<SomeObject>> copy;

{
Locker locker(&mutes);
copy = std::vector<std::shared_ptr<SomeObject>>(
list.begin(), list.end()
)
}
for (auto it = copy.begin(), it != copy.end(); ++it) {
it->Procss(); // This may take time/add/remove to the list
}
}
};

一个线程运行Process。多个线程运行添加/删除。

引用计数是否安全且始终正确 - 或者应该在其周围放置一个互斥体?

最佳答案

是的,旨在要求引用计数是线程安全的标准(在 §20.8.2.2,至少从 N3997 开始)。

对于像 Add 这样的简单情况:

void Add(std::shared_ptr<SomeObject> o) { 
Locker locker(&mutex);
list.push_back(std::make_shared<SomeObject>(o).
}

...标准中的保证足够强大,您不需要互斥量,因此您可以:

void Add(std::shared_ptr<SomeObject> o) { 
list.push_back(std::make_shared<SomeObject>(o).
}

对于您的某些操作,线程安全引用计数是否一定会避免您的互斥量这一点并不清楚。例如,在您的 Process 中,您有:

   {
Locker locker(&mutes);
copy = std::vector<std::shared_ptr<SomeObject>>(
list.begin(), list.end()
)
}

这会将整个复制作为一个原子操作执行——在复制过程中没有其他任何东西可以修改列表。这可确保您的拷贝为您提供列表的快照,与拷贝启动时的情况完全相同。如果您消除互斥体,引用计数仍然有效,但是您的拷贝可能会反射(reflect)在制作拷贝时所做的更改。

换句话说,shared_ptr 的线程安全只保证每个单独的递增或递减是原子的——它不能保证整个列表的操作是原子的,就像互斥锁在这种情况。

由于您的 list 实际上是一个 vector,您应该能够将复制代码稍微简化为 copy = list

另请注意,您的 Locker 似乎是 std::lock_guard 提供的子集。看来你可以使用:

std::lock_guard<std::mutex> locker(&mutes);

...很容易就位。

关于c++ - 引用计数线程安全吗,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29048227/

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