在 C++ And Beyond 的这段剪辑的开头附近,我听到了一些关于std::async
. 我有两个问题:
对于初级开发人员,是否有一套规则来说明在使用时应该做什么以及应该避免什么
std::async
?这段视频中存在哪些问题?它们与本文有关吗?
在 C++ And Beyond 的这段剪辑的开头附近,我听到了一些关于std::async
. 我有两个问题:
对于初级开发人员,是否有一套规则来说明在使用时应该做什么以及应该避免什么std::async
?
这段视频中存在哪些问题?它们与本文有关吗?
有几个问题:
std::async
如果没有启动策略,则运行时库可以选择是启动新线程还是在调用的线程中get()
或wait()
将来运行任务。正如 Herb 所说,这是您最可能想要使用的情况。问题在于,这让运行时库的 QoI 开放以获得正确的线程数量,并且您不知道任务是否会拥有自己的线程,因此使用线程局部变量可能会出现问题。据我了解,这就是斯科特所关心的。
在您显式调用or之前,使用 的策略std::launch::deferred
实际上不会运行任务。这几乎不是你想要的,所以不要那样做。get()
wait()
使用策略std::launch::async
启动一个新线程。如果您不跟踪您拥有多少线程,这可能会导致运行的线程过多。
Herb 担心std::future
析构函数的行为,它应该等待任务完成,尽管 MSVC2012 有一个错误在于它不等待。
对于初级开发人员,我建议:
std::async
与默认启动策略一起使用。对于使用默认策略的建议,我完全不同意。
如果您经历了设计独立计算单元的痛苦,您可能不会期望它们在六个 CPU 旋转它们的拇指时按顺序运行,这可能“合法地”发生,具体取决于您选择的编译器。
默认行为的隐含假设是一些复杂的线程池机制将优化任务放置(可能让一些在调用者的 CPU 上按顺序运行),但这纯粹是幻想,因为没有指定 C++ 运行时必须做什么(这会走无论如何都超出了编译器运行时的范围)。
在我看来,这更像是设计上未定义的行为。
一个名为“async”的类应该启动异步执行单元,除非某些明确和确定的行为参数另有说明。
坦率地说,除了调试目的,我看不到 for 的用途launch::deferred
,除非您打算编写自己的伪调度程序,在这种情况下,您最好使用纯线程。
所以我的建议是指定launch::async
何时使用async
, (告诉编译器类似“嘿,我想要一些异步任务,但真的是async
异步的,好吗?”)如果您只想按顺序执行任务,则根本不要使用。
如果您的异步任务遇到问题,可以方便地恢复到deferred
策略以更轻松地调试它们,但仅此而已。