在 C++03 中,我将
pthread
与自建线程池一起使用,该线程池始终保持几个线程运行(因为 pthread_create
很慢),这样我就可以为小任务启动线程,而无需考虑性能问题。
现在,在 C++11 中我们有了
std::thread
。我想该标准没有说明具体的实现,所以我的问题是关于标准库的实现。他们通常会选择构建 std::thread
成本低廉的池化方法(例如,不会在 posix 上调用 pthread_create
),还是 std::thread
只是一个包装器?
换句话说,C++11 中是否仍然推荐使用线程池,或者我应该在需要时创建一个
std::thread
并将性能留给标准库?
一般来说,
std::thread
应该是底层系统原语的最小包装器。例如,如果您在 pthread
平台上,您可以使用以下程序进行测试,无论您创建多少个线程,它们都是使用唯一的 pthread_t
id 创建的(这意味着它们是动态创建的,并且不是从线程池借来的):
#include <assert.h>
#include <mutex>
#include <set>
#include <thread>
#include <vector>
#include <pthread.h>
int main() {
std::vector<std::thread> workers;
std::set<long long> thread_ids;
std::mutex m;
const int n = 1024;
for (int i = 0; i < n; ++i) {
workers.push_back(std::thread([&] {
std::lock_guard<std::mutex> lock(m);
thread_ids.insert(pthread_self());
}));
}
for (auto& worker : workers) {
worker.join();
}
assert(thread_ids.size() == n);
return 0;
}
所以线程池仍然很有意义。也就是说,我看过一个视频,其中 C++ 委员会成员讨论了有关
std::async
(IIRC) 的线程池,但我现在找不到它。
A
std::thread
是一个执行线程。时期。它从哪里来,如何到达那里,是否存在一些“实际”线程池等,都与标准无关。只要它像线程一样,它就可以是std::thread
。
现在,
std::thread
很可能是一个现实生活中的操作系统线程,而不是从线程池或其他任何东西中提取的东西。但 C++11 理论上确实允许将 std::thread
实现为从池中提取的东西。
std::thread
应该非常便宜,它是低级的东西。据我了解,标准库实现可能会尽可能紧密地包装底层操作系统机制,因此您可以假设线程创建的开销是相似或等效的。
我不知道任何具体的实现,但这是我从阅读C++ Concurrency In Action中获得的二手理解,该标准建议他们使用最有效的实用方法。作者当然似乎认为与 DIY 相比,成本或多或少可以忽略不计。
该库在概念上与 Boost 类似,因此我想使用 Boost 实现来得出一些结论不会太牵强。
基本上,我认为您的问题没有直接答案,因为它只是没有指定。虽然在我看来,我们更有可能看到非常薄的包装器实现,但我认为如果线程池提供了效率优势,库编写者就不会受到使用线程池的限制。
首先,正如您提到的,C++ 标准基本上没有指定库的实现。 但是 C++ 标准库的实现者应该遵守“as-if”规则。
例如,这意味着
std::thread
的构造函数应表现为 就像创建了 新线程一样,无论是底层 API 的精简包装还是线程池等高效实现。 (这里,“线程”是指 C++11 规范中抽象的执行线程,而不是具体的操作系统本机线程)
关于线程池的实现;
thread_local
变量),并且它们应在运行时协同工作。因此,我假设大多数
std::thread
实现只是底层线程 API 的包装。