std::async使用std::launch::async策略未启动新线程

4
如果我使用std::launch::async策略启动std::async,它不应该在新线程中启动每个异步任务吗?目前看来,新的异步任务会移动到刚完成工作的线程上。我正在使用VC11编译器。从输出结果可以看出,当使用std::async启动一个新的worker(例如,一个worker多次获取ID为34500的线程)时,它会在先前完成的线程中启动。我的std::async理解是否有误,还是有一些类似于工作窃取队列的底层机制?
Worker (ID=24072) starting.
Worker (ID=34500) starting.
Worker (ID=32292) starting.
Worker (ID=31392) starting.
Worker (ID=17976) starting.
Worker (ID=31580) starting.
Worker (ID=33512) starting.
Worker (ID=33804) starting.
Worker 32292 finished.
Worker (ID=32292) starting.
Worker 17976 finished.
Worker (ID=17976) starting.
Worker 31580 finished.
Worker (ID=31580) starting.
Worker 34500 finished.
Worker (ID=34500) starting.
Worker 34500 finished.
Worker (ID=34500) starting.
Worker 32292 finished.
Worker (ID=32292) starting.
Worker 17976 finished.
Worker (ID=17976) starting.
Worker 34500 finished.
Worker 17976 finished. 
Worker 31580 finished.
Worker 32292 finished.
Worker 33804 finished.
Worker 31392 finished.
Worker 33512 finished.
Worker 24072 finished.

1
我认为实现允许使用线程池来处理新任务,或者至少这是我记得的意图。 - Xeo
2个回答

11
如果我使用std::launch::async策略启动std::async,它不应该在新线程中启动每个异步任务吗?
规范要求异步操作被执行“就像在一个新的执行线程中一样”(C++11 §30.6.8/11)。这里重要的词是:“就像”。如果行为与创建新线程相同,则可以重用已经运行的工作线程。例如,具有thread_local存储类的变量必须在在单个线程上执行的异步操作之间进行重置。
不需要重置线程标识符,因为线程标识符仅在其运行时唯一标识线程。如果线程终止,可能会启动另一个线程并使用第一个线程的标识符。
是否存在底层的工作窃取队列或类似的东西?
这取决于具体实现。Visual C++ 2012实现的C++11线程支持库是基于Concurrency Runtime (ConcRT)构建的,其中包括一个工作窃取任务调度程序。

1
太好了,我之前不知道 ConcRT。谢谢! - SiimKallas

6

詹姆斯是对的,但有一个修正:微软对launch::async的实现是不正确的。C++并发工作组在Redmond进行了详细讨论。Visual C++ 2012还处于测试版阶段,因此他们可能会更改实现以符合标准。


感谢博客链接,Bartosz!参加学习小组会议会很酷。从您的博客文章中可以看出,VC2012不符合标准的原因是它没有重置线程本地状态。这是正确的吗?我只是想确保我理解了不符合标准的程度。我最不想做的就是给人们提供错误信息 :-) - James McNellis
线程本地变量的销毁是一个问题。主要问题涉及另一个问题:使用有限的固定线程池可能会陷入死锁状态。想象一下,所有可用的线程都在运行阻塞等待剩余任务发送消息的任务。另一方面,这些剩余任务正在等待池线程变得可用。如果所有以launch::async启动的任务都在单独的线程中并发运行,则永远不会发生这种情况。 - Bartosz Milewski
我在使用Visual C++ 2013 Update 2时,刚刚用完std::async TP的线程。达到了一个上限(没有进行精确测量,但是它是以10为单位测量的),池就无法扩展超过该限制(即使使用了std::launch::async)。转换为std::thread后,限制消失了。没想到会出现这种行为... - Jörgen Sigvardsson

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接