我正在尝试了解std::thread
中的一些基本概念,但我仍然对此并不自信。潜在的问题是:
当我超过std::thread::hardware_concurrency()
的值时实际发生了什么,就像我在下面所做的那样?
我知道该方法只是一个提示,但是在这种情况下,8应该是正确的。我没有看到警告或错误,那么实际上是什么情况?
我怀疑这与我对join()
和detach()
缺乏了解有关,这使我想到了第二个问题。
我知道,如果我在没有join()
或detach()
的情况下启动线程,则会遇到运行时错误。从阅读和观察中我了解到,join()
导致线程阻塞直到完成执行,而detach()
基本上相反,允许线程运行直到完成为止,有可能打开罐头如果该线程不是自己终止的,则为蠕虫。
根据我的观察,看来join()
和detach()
的使用是互斥的。这是错的吗?为什么我需要在同一线程上使用join()
和detach()
?
就我的第一个问题而言,我什至无法开始猜测。我期望出现某种类型的运行时错误,或者出现一些更明显的强制阻塞。
#include <ctime>
#include <cstdlib>
#include <iostream>
#include <thread>
#include <vector>
std::vector<unsigned> getNumbers(unsigned n)
{
std::vector<unsigned> out;
while(n > 0)
{
out.push_back(rand());
n--;
}
return out;
}
int main() {
srand(time(nullptr));
std::vector<std::thread> threads;
unsigned maxThreads = std::thread::hardware_concurrency();
std::cout << "Max threads: " << maxThreads << std::endl;
unsigned tooManyThreads = maxThreads + 5;
for(auto i = 0; i < tooManyThreads; i++)
{
threads.push_back(std::thread(getNumbers,(rand() % 10000 + 1)));
std::cout << "Starting thread " << i << " ("
<< threads.back().get_id() << ")" << std::endl;
threads.back().detach();
}
for(auto i = 0; i < tooManyThreads; i++)
{
if(threads.at(i).joinable())
{
threads.at(i).join();
std::cout << "Joining " << i << std::endl;
}
}
return 0;
}
答案 0 :(得分:2)
在这种情况下,您似乎对“线程”的含义感到困惑。线程有两种:cell.layer.zPosition = CGFloat(numberOfRows - indexPath.row)
是software thread,而std::thread
返回hardware threads的数量。
软件线程不需要专用的硬件线程,操作系统可以并且将调度不同的软件线程来共享相同的硬件线程。实际上,软件线程通常比计算机上的硬件线程多几个数量级。
答案 1 :(得分:2)
在任何给定时间,计算机上都有数千个线程在运行。它们大多数来自其他程序或进程,其中有数百或数千在后台运行。 (如果您在Windows中打开TaskManager或在Linux命令提示符下键入htop
,则可以看到它们)。
那么std::thread::hardware_concurrency
是什么?这是可以同时执行的线程数。如果您有8个逻辑核心,则只能同时执行8个线程。所有其他线程都被“暂停”,至少直到轮到它们运行为止。
这听起来像是一个矛盾:怎么可能有成千上万的线程而没有成千上万的内核?答案是操作系统调度线程。每个活动线程都可以运行,并且发生得足够快,以至于人们不会注意到延迟,但是这些线程实际上并没有同时执行。
基本上,std::thread::hardware_concurrency
告诉您使用线程的最大可能速度。如果您有8个核心,则使用线程并行化的最大速度为8倍。可以启动更多的线程,这是很好的,许多程序这样做是因为它们被设计为使不同的线程可以处理不同类型的任务(例如一个线程可以读取/写入文件,另一个线程可以控制GUI,另一个线程可以处理)。在后台运行,并且另一个线程可能会与网络通信),但实际上并不会使您的程序运行得更快。