c++ - 线程安全的 unique_ptr move

标签 c++ c++11 thread-safety move-semantics unique-ptr

是否可以使用 C++11 原子操作安全地 move unique_ptr?

目前我有这样的代码

std::unique_ptr<SyncToken> DataManager::borrowSyncToken()
{
    std::unique_lock<std::mutex> syncTokenLock(syncTokenMutex);
    return std::move(syncToken);
}

我想知道是否有更优雅的方式,比如简单地声明:

std::atomic<std::unique_ptr<SyncToken>> syncToken;

并避免互斥量的需要。或者我可能根本不需要关心这里的锁并且 std::move 已经是原子的了?

经过到目前为止的研究,在我看来:

  • std::move 本身不是原子的,需要有一些同步,否则 2 个线程同时调用我的方法可能会以一些未定义指针的 2 个拷贝结束。
  • std::atomic 声明为我编译,但我不知道如何初始化它并进行 move 。

最佳答案

不,这是不可能的。

您传递给 std::atomic 的值 T 需要可平凡复制,而 std::unique_ptr 则不是。 std::atomic::loadstd::atomic::store 等操作按值获取 T 对象。

std::atomic 中打包一些东西也不会从值原子中进行操作。

在原子上下文中使用 std::unique_ptr 时,您必须考虑这样一个事实,即在管理资源时可能会遇到问题。您永远不知道有多少线程仍在引用您的数据,这个问题可以通过使用原子引用计数的 std::shared_ptr 来解决。 (您需要使用 std::atomic_is_lock_free 函数检查它是否真的是原子的。)

在查看您的代码时,我也偶然发现了 borrowSyncToken 函数的意图。它被称为借用,但您通过移出 std::unique_ptr 将 token 的所有权传递给调用者,所有权如何传回以及当 DataManager 当前不拥有 token ?

关于c++ - 线程安全的 unique_ptr move ,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13866743/

相关文章:

c++ - 异步事件通知的思路

c++ - macOS Catalina 屏幕录制权限

使用 std 安全指针相互链接的 c++ 类 (c++)

c++ - 初始化顺序和移动语义

Ruby 暂停线程

c++ - 这两个比较表达式是否相同?

c++ - 过滤 Eclipse 的 C++ 内容辅助

c++ - 混合部分模板特化和默认模板参数

python - urllib2 和 cookielib 线程安全

c - 如何使包含在不同类线程中的全局变量在 c 中安全