【问题标题】:Move vector between threads在线程之间移动向量
【发布时间】:2014-01-22 10:54:59
【问题描述】:

我有一个线程通过这样的公共接口持续收集数据项:

class MyThread {
public:
    class Item {
        // ...
    };

    startup();
    shutdown();

    bool hasItems() const;

    // retrieve collected items
    std::vector<Item>&& items();
private:
    std::mutex itemMutex;
    std::vector<Item> currentItems;
};

检索项目还应清除线程的项目列表。我返回一个右值,以便在调用方调用移动构造函数。当然,检索项目应该是线程安全的,因此实现如下所示:

std::vector<MyThread::Item>&& MyThread::items() {
    std::lock_guard<std::mutex> lock(itemMutex);
    return std::move(currentItems);
}

我认为这里的锁被释放得太早了:该函数返回右值向量,但是当std::lock_guard 被销毁并释放互斥锁时,不一定会使用它调用移动构造函数。所以据我了解,这不是线程安全的。我对吗?我怎样才能使它成为线程安全的?

【问题讨论】:

  • 如果你改变你的函数来返回一个std::vector&lt;MyThread::Item&gt;而不是一个右值引用那么没有问题。

标签: c++ multithreading c++11 move-semantics


【解决方案1】:

你是对的,它不是线程安全的,因为移动将在方法返回后发生,此时锁将被释放。要修复它,只需将向量移动到局部变量中并返回它:

std::vector<MyThread::Item> MyThread::items() 
{
    std::lock_guard<std::mutex> lock(itemMutex);
    return std::vector<MyThread::Item>(std::move(currentItems));
}

【讨论】:

  • 返回的值还是我调用std::vector&lt;MyThread::Item&gt; list (myThreadInstance.items());时会移动的右值吗?在我看来,这似乎会调用深层副本。
  • 当您将其分配给本地 (std::vector&lt;MyThread::Item&gt; items=items()) 时,它将是一个右值。
  • 我相信,您不需要显式使用 std::move()。如果有一个 move-ctor,那么在返回值 (currentItems) 时无论如何都会使用它,所以简单地说:return currentItems; 就足够了。
  • @CouchDeveloper return currentItems; 仅在 currentItems 是函数局部变量时才有效。这里它是一个数据成员,所以std::move 是必需的。
【解决方案2】:

您必须记住,currentItem 在移出后处于“部分形成”状态(请参阅What lasts after using std::move c++11)。 在其中一个答案中有一个如何解决该问题的示例:

std::vector<MyThread::Item> MyThread::items() 
{
    std::lock_guard<std::mutex> lock(itemMutex);
    auto tmp =  std::move(currentItems);
    currentItems.clear();
    return tmp;
} 

我宁愿选择最直接的解决方案,让编译器完成繁重的工作:

std::vector<MyThread::Item> MyThread::items() 
{
    std::lock_guard<std::mutex> lock(itemMutex);
    std::vector<MyThread::Item> tmp;
    tmp.swap(currentItems);
    return tmp;
} 

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2023-03-15
    • 2022-06-19
    • 2014-09-03
    • 1970-01-01
    • 1970-01-01
    • 2013-01-24
    • 1970-01-01
    相关资源
    最近更新 更多