使用C ++ std :: future进行数据竞争。编译器重新排序

时间:2015-03-13 07:05:10

标签: c++ multithreading

我正在编写一个异步访问数据库的应用程序。在我的示例中,序列化由handleAllGroups函数处理。这个函数需要一个仿函数,它实际上适用于数据库对象。由于我对返回的类型不满意,因此我将在延迟的异步调用中包装所有内容,以创建我想要的内容。一切似乎都很顺利。我仍然有点担心数据争用,因为我没有原子或互斥保护。

问题:编译器是否有可能决定在std::move(*data)之前执行fut.wait()?这很重要,因为数据与其他线程共享! (ftor采用共享所有权,并通过handleAllGroups在数据库线程中调用)

感谢任何帮助!

handleGroupCol_ftor
make_getGroupNamesFtor(std::shared_ptr<std::vector<std::string>>& data);

std::future<MayBeStrVector>
getAllGroupNames()
{
  // FIXME: This function is fine, but relies on ftor not
  // sharing ownership of data in other places (the move)
  auto data = std::make_shared<std::vector<std::string>>();
  auto ftor = make_getGroupNamesFtor(data);
  return std::async(std::launch::deferred,
        [data](std::future<result>&& fut)->MayBeStrVector{
          fut.wait();
          return {fut.get(), std::move(*data)};
        },
        handleAllGroups(ftor));
}

2 个答案:

答案 0 :(得分:1)

假设所有写入data指向另一个线程的内容在编写之前已经排序 - fut - 准备就绪,那么您就是安全的。 [futures.state] / P9:

  

调用成功设置共享存储结果的函数   state与(1.10)成功调用同步   检测由该设置产生的就绪状态。存储   结果(无论正常还是异常)进入共享状态   与(1.10)同步从呼叫到a的成功返回   等待共享状态的功能。

在标准版中没有陷入困境,这里的关系同步意味着在调用之前排序的所有内容都将在线程设置结果中设置存储结果 > wait()电话后排序的所有内容。

答案 1 :(得分:0)

是的,future :: wait()与使未来有效同步(例如返回异步或设置一个promise),所以你所做的事情是安全的,因为我可以从代码的那一部分看出来。

然而,我发现你使用共享指针有问题:给另一个线程的共享指针意味着给予该线程(共享)所有权,但是对shared_ptr的内容调用std :: move几乎和手动调用一样糟糕删除它。