根据 C++ 标准的 [futures.async]/3 项目符号 1,当使用启动策略f
传递函数时,将“就像在新的执行线程中一样”运行。std::async
std::launch::async
f
鉴于它f
可以做任何事情,包括无限循环和永远阻塞,一个实现如何提供在f
自己的线程上运行而不实际在自己的线程上运行的行为?也就是说,实现如何利用标准提供的“好像”摆动空间?
根据 C++ 标准的 [futures.async]/3 项目符号 1,当使用启动策略f
传递函数时,将“就像在新的执行线程中一样”运行。std::async
std::launch::async
f
鉴于它f
可以做任何事情,包括无限循环和永远阻塞,一个实现如何提供在f
自己的线程上运行而不实际在自己的线程上运行的行为?也就是说,实现如何利用标准提供的“好像”摆动空间?
查看出现在此处和此处的 C++ 引用,似乎“好像”的目标是让库实现者有一定程度的自由度。例如,它说
如同由 std::thread(std::forward(f), std::forward(args)...) 产生的,除非函数 f 返回值或抛出异常,它存储在共享状态通过 async 返回给调用者的 std::future 访问。
在第一个来源中,并且
就好像一个线程对象是用 fn 和 args 作为参数构造的,并且访问返回的未来的共享状态加入它
在第二。所以看起来行为类似于 ofstd::thread
但可能以不同的方式实现。这很有趣,因为您在此处引用的短语thread of execution与std::thread
. 尽管如此,似乎两个消息来源都理解这种方式。
正如François Andrieux建议的那样,另一个选项可能是允许使用线程池,如第一个来源中所述:
模板函数 async 异步运行函数 f(可能在一个单独的线程中,该线程可能是线程池的一部分)
我能想到的一些方法可以f
“好像”在一个新线程上运行而不实际这样做是如果f
实际上不使用与其他线程共享的任何状态;然后实现可以将它作为一个单独的进程运行(因为它不需要共享内存空间)它也可以在主线程上运行它作为另一个函数调用(如果它可以证明它f
不会阻塞或具有可观察的一面以这种方式运行时会有所不同的效果)。它也可以安排在现有的(但空闲的)线程(线程池)上运行。
如果你想傻,我想你也可以考虑根本不运行的概念f
,因为不能保证新线程何时会被操作系统安排运行,所以一个邪恶的实现可能只是说操作系统从不调度除主线程之外的任何线程,因此根本不运行f
相当于在新线程上调度它。当然,这是愚蠢/愚蠢的,任何理智的实现都不会这样做 - 但理论上该语言允许这种退化的实现(我认为)。
此解决方案的优点是当您针对多线程世界中的特定角色优化实施时。由于我参与了软件更新程序,我将使用这样的示例。出于优化原因,您可以调用:
std::thread::hardware_concurrency();
您将收到:
返回实现支持的并发线程数。
假设您的结果等于 4。您希望并行执行许多更新。主线程正在监视期货列表(左 3),并不时检查它是否完成,如果完成,则从 ToDo 列表中执行下一步。例如,如果您要更新不同类型的内存,如 1-FileSystem、2-EEPROM、3-NOR 内存或类似的东西,这里的利润就可以了。没有延迟地检查循环是没有好处的,所以你想在检查之间给第 4 个线程一个任务。您正在编写挖掘比特币 50 毫秒的函数 :) 并在检查之间延迟触发它。
然后正如你提到的,我们有:
标准提供的“好像”摆动空间的优势
AFAIK C++ 运行时能够管理一些与标准线程不同的内部(或专用)线程。
我的猜测(我仍在学习 C++ 的高级特性)是,有了这个std::launch::async
标志,std::async()
它将f
在一个新的内部线程中启动。
您可以使用. f
_ 在这种情况下,异常将在被调用线程上处理,主代码必须获取.std::thread
f
使用内部线程,返回值和最终异常被存储到线程中std::future
,由线程返回std::async()
并在线程之间共享。
所以“好像”代表“好像我启动f
但std::thread
我不必”。但可以肯定的是,f
它将在新线程上运行。
要回答您关于实现的问题,一旦运行时已经实现了标准线程,只需努力将它们专门用于特定用途。另请参阅支持并行化的算法的执行策略。
我看到“f 将像在新的执行线程中一样运行”的主要思想是f将异步运行。它应该是新线程还是其他什么是实现细节。
我能想到的唯一没有 Thread 的解决方案是昨天的 Time-Slicing,它是一种多任务处理形式。这些功能必须是可重入的。在这种情况下,每个函数都将像在不同的线程上一样运行,尽管实际上它们在单个线程上。
在文档中,它在那里声明,
模板函数 async 异步运行函数 f (可能在一个单独的线程中,它可能是线程池的一部分)并返回一个 std::future ,它最终将保存该函数调用的结果。