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++ - 如何在不编译的情况下执行 C++ 代码?

c++ - Qt 库组件可以调用 qDebug() 或类似函数吗?

c++ - 高斯过程的准随机数发生器

java - 为什么 notifyAll() 没有唤醒这个例子中的所有线程?

c++ - 如何从 vector 中弹出共享指针并转换为 unique_ptr

c++ - boost::shared_ptr 断言错误与 boost::asio:io_service

c++ - 如何使用内联汇编模拟以下 C++ 代码?

multithreading - 我如何保证一个线程将比另一个线程长寿,从而允许我在没有“静态”的情况下共享引用?

c++ - 并行执行不会更新我的变量

c++ - 在范围内保持 shared_ptr