为啥 C++ 标准库中没有线程池?
Posted
技术标签:
【中文标题】为啥 C++ 标准库中没有线程池?【英文标题】:Why is there no thread pool in C++ standard library?为什么 C++ 标准库中没有线程池? 【发布时间】:2021-11-10 10:59:15 【问题描述】:自 C++11 以来,C++ 中并行/并发编程工具的数量激增:线程、异步函数、并行算法、协程……但是流行的并行编程模式:thread pool?
据我所知,标准库中没有任何东西直接实现这一点。通过std::thread
进行线程化可以用来实现线程池,但这需要人工。通过std::async
的异步函数可以在新线程(std::launch::async
)或调用线程(std::launch::deferred
)中启动。
我认为 std::async
可以很容易地支持线程池:通过另一个启动策略 (std::launch::thread_pool
) 在隐式创建的全局线程池中执行任务;或者可能有一个std::thread_pool
对象加上std::async
的重载,它需要一个线程池。
是否考虑过这样的事情,如果考虑过,为什么会被拒绝?或者是否有我缺少的标准解决方案?
【问题讨论】:
你为什么确定std::async
不使用线程池?
要么是因为1.它没有被提议要么2.这样的提议没有被接受。
我不知道,认为他们想将 stl 限制在更原始的构建块上。不,没有标准的解决方案,但我有一个。
将线程池纳入标准并不容易。我不知道它是如何详细介绍的,但考虑到 C++11 引入了std::thread
,而只有 C++20 引入了std::jthread
。我想在 C++20 引入 std::jthread
之前需要时间来收集新线程工具的经验,这仍然是低水平的。我希望更高级别的抽象更不容易标准化
有许多不同类型的线程池,为了某些目的选择“最好的”需要非常详细的应用程序知识和(通常)主机系统的属性。这些特征增加了就应该标准化的内容达成一致的难度。对线程池的标准化支持(比如)针对 Windows 进行了良好调整,但针对其他操作系统调整不佳,这与 C++ 的核心理念背道而驰。
【参考方案1】:
原则上std::async
可以使用线程池,在我看来,允许这是意图。但在实践中,thread_local
的存在使其变得困难。
从cppreference 到std::async
和std::launch::async
:
[...] 在新的执行线程上执行可调用对象
f
(所有线程局部变量都已初始化),就好像由std::thread(std::forward<F>(f), std::forward<Args>(args)...)
产生一样[...]
如果函数包含任何本地thread_local
变量,并且如果std::async
使用线程池,则运行该函数的行为将std::async
可能与std::thread
的行为不同。
一个例子可能是thread_local
在第二次被同一个线程调用时可能没有它的初始值。如果你改用std::thread
,它总是有初始值。
行为不同的另一种方式是thread_local
对象的析构函数不会以相同的方式运行std::async
和std::thread
。微软尝试使用线程池就说明了这一点,我怀疑这会吓跑其他人尝试它。您可以在此处阅读有关此不符合项的信息:In Visual Studio, thread_local
variables' destructor not called when used with std::async, is this a bug?。
为了完全符合要求,无论如何,实现都需要“重置”所有thread_local
对象。这需要编译器支持,并且开始看起来很像开始一个新线程。
【讨论】:
直接链接到 MSVC 的 Stdlib 中的 bug github.com/microsoft/STL/issues/949以上是关于为啥 C++ 标准库中没有线程池?的主要内容,如果未能解决你的问题,请参考以下文章