std ::线程最大并发线程

std::thread maximum concurrent threads

本文关键字:线程 并发 std      更新时间:2023-10-16

我正在尝试理解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;
} 

您似乎对"线程"在这种情况下的含义感到困惑。有两种线程:std::thread是A 软件线程,而std::thread::hardware_concurrency()返回硬件 threads的数字。

SOFWARE线程不需要专用的硬件线程,操作系统可以并且将安排不同的软件线程以共享相同的硬件线程。实际上,通常比计算机上有硬件线程的软件线程多几个数量级。

在任何给定时间,计算机上都有几千个线程。他们中的大多数来自其他程序或过程,其中有数百万或数千个在后台运行。(如果您在Windows中打开TaskManager,或将htop键入Linux命令提示符,则可以看到它们。

那么什么是std::thread::hardware_concurrency?可以同时执行的线程数。如果您有8个逻辑内核,则只能同时执行8个线程。所有其他线程都是"暂停"的,至少在轮到他们运行之前。

这听起来像是矛盾:如何有成千上万的线没有数千个核心?答案是操作系统计划线程。每个主动线程都会转弯,并且它很快就会发生,以致人类不会注意到延迟,但是这些线程实际上并未同时执行。

基本上,std::thread::hardware_concurrency告诉您使用线程的最大速度。如果您有8个核心,则使用线程并行化的最大速度为8倍。可以启动更多的线程是可以的,而且许多程序之所以这样做,是因为它们设计的,以便不同的线程处理不同类型的任务(例如一个线程可能会读取/写入文件,另一个线程可以控制GUI,另一个线程可能会处理背景中的内容,另一个线程可能会与网络交谈(,但实际上不会使您的程序运行速度更快。