18

在 C++ And Beyond 的这段剪辑的开头附近,我听到了一些关于std::async. 我有两个问题:

  1. 对于初级开发人员,是否有一套规则来说明在使用时应该做什么以及应该避免什么std::async

  2. 这段视频中存在哪些问题?它们与本文有关吗?

4

2 回答 2

23

有几个问题:

  1. std::async如果没有启动策略,则运行时库可以选择是启动新线程还是在调用的线程中get()wait()将来运行任务。正如 Herb 所说,这是您最可能想要使用的情况。问题在于,这让运行时库的 QoI 开放以获得正确的线程数量,并且您不知道任务是否会拥有自己的线程,因此使用线程局部变量可能会出现问题。据我了解,这就是斯科特所关心的。

  2. 在您显式调用or之前,使用 的策略std::launch::deferred实际上不会运行任务。这几乎不是你想要的,所以不要那样做。get()wait()

  3. 使用策略std::launch::async启动一个新线程。如果您不跟踪您拥有多少线程,这可能会导致运行的线程过多。

  4. Herb 担心std::future析构函数的行为,它应该等待任务完成,尽管 MSVC2012 有一个错误在于它不等待。

对于初级开发人员,我建议:

  • std::async与默认启动策略一起使用。
  • 确保你明确地等待你所有的未来。
  • 不要在异步任务中使用线程本地存储。
于 2012-09-20T10:27:45.880 回答
7

对于使用默认策略的建议,我完全不同意。

如果您经历了设计独立计算单元的痛苦,您可能不会期望它们在六个 CPU 旋转它们的拇指时按顺序运行,这可能“合法地”发生,具体取决于您选择的编译器

默认行为的隐含假设是一些复杂的线程池机制将优化任务放置(可能让一些在调用者的 CPU 上按顺序运行),但这纯粹是幻想,因为没有指定 C++ 运行时必须做什么(这会走无论如何都超出了编译器运行时的范围)。

在我看来,这更像是设计上未定义的行为。

一个名为“async”的类应该启动异步执行单元,除非某些明确和确定的行为参数另有说明。

坦率地说,除了调试目的,我看不到 for 的用途launch::deferred,除非您打算编写自己的伪调度程序,在这种情况下,您最好使用纯线程。

所以我的建议是指定launch::async何时使用async, (告诉编译器类似“嘿,我想要一些异步任务,但真的是async异步的,好吗?”)如果您只想按顺序执行任务,则根本不要使用。

如果您的异步任务遇到问题,可以方便地恢复到deferred策略以更轻松地调试它们,但仅此而已。

于 2014-12-13T18:38:56.037 回答