gpt4 book ai didi

c++ - 使用 shared_ptr 在写时复制

转载 作者:可可西里 更新时间:2023-11-01 17:59:57 26 4
gpt4 key购买 nike

所以我有一个简单的 cow_ptr .它看起来像这样:

template<class T, class Base=std::shared_ptr<T const>>
struct cow_ptr:private Base{
using Base::operator*;
using Base::operator->;
using Base::operator bool;
// etc

cow_ptr(std::shared_ptr<T> ptr):Base(ptr){}

// defaulted special member functions

template<class F>
decltype(auto) write(F&& f){
if (!unique()) self_clone();
Assert(unique());
return std::forward<F>(f)(const_cast<T&>(**this));
}
private:
void self_clone(){
if (!*this) return;
*this = std::make_shared<T>(**this);
Assert(unique());
}
};

这保证它拥有一个非常量 T并确保它是 unique当它.write([&](T&){})就这样吧。

弃用 .unique()似乎表明这种设计是有缺陷的。

我猜如果我们从 cow_ptr<int> ptr 开始与 1在线程A中,传递给线程B,使其唯一,修改为2 , 通过 ptr返回并在线程中阅读 A我们已经产生了竞争条件。

我该如何解决这个问题?我可以简单地在 write 中添加一个内存屏障吗? ?哪一个?还是问题更根本?

由于 x86 内存一致性超出 C++ 要求,x86 上的症状是否不太可能?

最佳答案

unique() 已被弃用,因为它不是线程安全的:p0521r0

我认为 std::shared_ptr::use_count() 也是如此,但它并没有被弃用。查看关于 cppreference.com 的评论

最后,std::shared_ptr 并不是 100% 线程安全的。如果您从多个线程访问、复制或重置/销毁单个 shared_ptr 实例,则应使用锁守卫。所以,我同意你的猜测。 Thread safety of shared_ptr :

All member functions (including copy constructor and copy assignment) can be called by multiple threads on different instances of shared_ptr without additional synchronization even if these instances are copies and share ownership of the same object. If multiple threads of execution access the same instance of shared_ptr without synchronization and any of those accesses uses a non-const member function of shared_ptr then a data race will occur; the shared_ptr overloads of atomic functions can be used to prevent the data race.

关于您建议的修复:
我不认为,在现有类中引入锁或内存屏障(你是说原子变量?)会改变线程安全方面的任何事情。您的类继承了 shared_ptr,它在所有用例中都不是线程安全的。这与您的 unique() 调用无关。

要清楚:
从多个线程调用 shared_ptr 的本地拷贝,指向相同的资源是线程安全的。多个线程对单个 shared_ptr 实例的调用不是线程安全的。

关于c++ - 使用 shared_ptr 在写时复制,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46700521/

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