std::thread 最大并发线程数

mre*_*555 1 c++ concurrency multithreading stdthread

我正在尝试理解 中的一些基本概念std::thread,但我对此仍然没有信心。根本问题是:

当我超过 的值时实际发生了什么std::thread::hardware_concurrency(),就像我在下面所做的那样?

我知道该方法只是一个提示,但在这种情况下 8 应该是准确的。我没有看到任何警告或错误,那么到底发生了什么?

join()我怀疑这与我对和缺乏理解有关detach(),这让我想到了第二个问题。

join()我知道如果我在没有 a或 a 的情况下启动线程detach(),我将收到运行时错误。据我从阅读和观察中了解到,join()导致线程阻塞直到完成执行,而detach()基本上相反,允许线程疯狂运行直到完成,如果该线程不终止,则可能会打开一罐蠕虫它自己的。

join()根据我的观察,和的用法似乎detach()是相互排斥的。这是错误的吗?为什么我需要在同一个线程上使用join()and ?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;
} 
Run Code Online (Sandbox Code Playgroud)

Pet*_*ell 5

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

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


J. *_*rez 5

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

\n\n

那么什么是std::thread::hardware_concurrency?它\xe2\x80\x99是可以同时执行的线程数。如果您有 8 个逻辑核心,则只能同时执行 8 个线程。所有其他线程都已暂停,至少直到轮到它们运行为止。

\n\n

这听起来像是一个矛盾:没有数千个核心怎么可能有数千个线程?答案是操作系统调度线程。每个活动线程都会轮流运行,并且它发生得足够快,人们不会注意到延迟,但这些线程实际上并不是同时执行的。

\n\n

基本上,std::thread::hardware_concurrency告诉您使用线程的最大可能速度。如果您有 8 个核心,则使用线程并行化的最大速度为 8 倍。启动更多线程就可以了,许多程序这样做是因为它们经过重新设计,以便不同的线程处理不同类型的任务(例如一个线程可以读/写文件,另一个线程可以读/写文件)可能会控制 GUI,另一个线程可能会在后台处理东西,另一个线程可能会与网络通信),但它实际上不会\xe2\x80\x99t 使你的程序运行得更快。

\n