c++ - 为什么不推荐使用 std::shared_ptr::unique() ?

标签 c++ multithreading shared-ptr c++17

std::shared_ptr::unique() 的技术问题是什么导致它在 C++17 中被弃用?

根据cppreference.com , std::shared_ptr::unique() 在 C++17 中被弃用为

this function is deprecated as of C++17 because use_count is only an approximation in multi-threaded environment.

我理解这对于 use_count() > 1 是正确的:当我持有对它的引用时,其他人可能同时放开他的引用或创建一个新拷贝。

但如果 use_count() 返回 1(这是我在调用 unique() 时感兴趣的内容),则没有其他线程可以更改该值以一种活泼的方式,所以我希望这应该是安全的:

if (myPtr && myPtr.unique()) {
    //Modify *myPtr
}

我自己搜索的结果:

我找到了这个文件:http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2016/p0521r0.html它提议弃用以响应 C++17 CD 评论 CA 14,但我找不到该评论本身。

作为替代方案,该论文建议添加一些注释,包括以下内容:

Note: When multiple threads can affect the return value of use_count(), the result should be treated as approximate. In particular, use_count() == 1 does not imply that accesses through a previously destroyed shared_ptr have in any sense completed. — end note

我知道当前指定 use_count() 的方式可能是这种情况(由于缺乏保证同步),但为什么解决方案不仅仅是指定这种同步,因此使上述模式安全吗?如果存在不允许此类同步的基本限制(或使其代价高昂),那么如何正确实现析构函数?

更新:

我忽略了@alexeykuzmin0 和@rubenvb 提出的明显案例,因为到目前为止我只在其他线程无法访问的shared_ptr 实例上使用了unique()他们自己。因此,该特定实例不会以不正当的方式被复制。

我仍然有兴趣了解 CA 14 到底是什么,因为我相信我的所有 unique() 用例只要保证与发生的任何事情同步就可以工作其他线程上的不同 shared_ptr 实例。所以它对我来说似乎仍然是一个有用的工具,但我可能会在这里忽略一些基本的东西。

为了说明我的想法,请考虑以下内容:

class MemoryCache {
public:
    MemoryCache(size_t size)
        : _cache(size)
    {
        for (auto& ptr : _cache) {
            ptr = std::make_shared<std::array<uint8_t, 256>>();
        }
    }

    // the returned chunk of memory might be passed to a different thread(s),
    // but the function is never accessed from two threads at the same time
    std::shared_ptr<std::array<uint8_t,256>> getChunk()
    {
        auto it = std::find_if(_cache.begin(), _cache.end(), [](auto& ptr) { return ptr.unique(); });
        if (it != _cache.end()) {
            //memory is no longer used by previous user, so it can be given to someone else
            return *it;
        } else {
            return{};
        }
    }
private:
    std::vector<std::shared_ptr<std::array<uint8_t, 256>>> _cache;
};

有什么问题吗(如果 unique() 实际上会与其他拷贝的析构函数同步)?

最佳答案

考虑以下代码:

// global variable
std::shared_ptr<int> s = std::make_shared<int>();

// thread 1
if (s && s.unique()) {
    // modify *s
}

// thread 2
auto s2 = s;

这里我们有一个经典的竞争条件:s2 可能(也可能不会)在线程 2 中创建为 s 的拷贝,而线程 1 在 如果.

unique() == true 表示没有人有一个 shared_ptr 指向同一个内存,但并不意味着任何其他线程无权访问初始 shared_ptr 直接或通过指针或引用。

关于c++ - 为什么不推荐使用 std::shared_ptr::unique() ?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41142315/

相关文章:

c++ - MSVC++ 中的 "Ch"是什么?

c++ - 在基类中调用 shared_from_this() 时的 bad_weak_ptr

c++ - 使用带有预分配指针的shared_ptr

AndroidObservable 从不在主线程上观察

c++ - 线程安全标准 :list C++

java - 在线程上设置中断标志

c++ - 在 UML 中绘制智能指针

C++ 对象不保存值

c++ - 使用额外模块错误 ocv_download 构建 opencv

c++ - 通过数学引用传递