5

是否可以使用 c++11 原子操作安全地移动 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 声明为我编译,但我不知道如何初始化它并采取行动。
4

1 回答 1

3

不,这是不可能的。

T您传递给的值std::atomic需要可以轻松复制,但事实std::unique_ptr并非如此。操作喜欢std::atomic::loadstd::atomic::store按值获取 T 个对象。

将某些东西打包在 astd::atomic中也不会使值原子操作。

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

在查看您的代码时,我还偶然发现的一件事是borrowSyncToken函数的意图。它被称为借用,但是您通过移出 将令牌的所有权传递给调用者,std::unique_ptr所有权如何传回以及当 DataManager 当前不拥有令牌时其他线程会得到什么?

于 2012-12-13T20:57:42.137 回答