std :: thread最大并发线程数

问题描述 投票:0回答:2

我试图理解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;
} 
c++ multithreading concurrency stdthread
2个回答
2
投票

您似乎对“线程”在此上下文中的含义感到困惑。有两种线程:std::threadsoftware thread,而std::thread::hardware_concurrency()返回hardware threads的数量。

软件线程不需要专用硬件线程,操作系统可以并将调度不同的软件线程来共享相同的硬件线程。事实上,软件线程通常比机器上的硬件线程多几个数量级。


2
投票

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

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

这可能听起来像是一个矛盾:如何拥有数千个没有数千个内核的线程?答案是操作系统安排线程。每个活动线程都转向运行,并且它发生得非常快,以至于人类没有注意到延迟,但这些线程实际上并没有同时执行。

基本上,std::thread::hardware_concurrency告诉你使用线程可能达到的最大速度。如果你有8个内核,使用线程并行化的最大速度是8倍。可以启动更多线程,并且很多程序都是这样做的,因为它们的设计是为了让不同的线程处理不同类型的任务(比如一个线程可以读/写文件,另一个线程可以控制GUI,另一个线程可以处理在后台的东西,另一个线程可能与网络通信),但它实际上不会让你的程序运行得更快。

© www.soinside.com 2019 - 2024. All rights reserved.