简体   繁体   English

C ++的递归线程使资源暂时不可用

[英]recursive threading with C++ gives a Resource temporarily unavailable

So I'm trying to create a program that implements a function that generates a random number (n) and based on n, creates n threads. 所以我试图创建一个程序,该程序实现一个函数,该函数生成一个随机数(n),并基于n创建n个线程。 The main thread is responsible to print the minimum and maximum of the leafs. 主线程负责打印最小和最大的叶子。 The depth of hierarchy with the Main thread is 3. 主线程的层次结构深度为3。

I have written the code below: 我写了下面的代码:

#include <iostream>
#include <thread>
#include <time.h>
#include <string>
#include <sstream>

using namespace std;


// a structure to keep the needed information of each thread
struct ThreadInfo
{
    long randomN;
    int level;
    bool run;
    int maxOfVals;
    double minOfVals;
};


// The start address (function) of the threads
void ChildWork(void* a) {

    ThreadInfo* info = (ThreadInfo*)a;

    // Generate random value n
    srand(time(NULL));
    double n=rand()%6+1;


    // initialize the thread info with n value
    info->randomN=n;
    info->maxOfVals=n;
    info->minOfVals=n;


    // the depth of recursion should not be more than 3
    if(info->level > 3)
    {
        info->run = false;
    }

    // Create n threads and run them
    ThreadInfo* childInfo = new ThreadInfo[(int)n];
    for(int i = 0; i < n; i++)
    {
        childInfo[i].level = info->level + 1;
        childInfo[i].run = true;
        std::thread tt(ChildWork, &childInfo[i]) ;
        tt.detach();
    }


    // checks if any child threads are working
    bool anyRun = true;
    while(anyRun)
    {
        anyRun = false;
        for(int i = 0; i < n; i++)
        {
            anyRun = anyRun || childInfo[i].run;
        }
    }

    // once all child threads are done, we find their max and min value
    double maximum=1, minimum=6;
    for( int i=0;i<n;i++)
    {
    //  cout<<childInfo[i].maxOfVals<<endl;


        if(childInfo[i].maxOfVals>=maximum)
            maximum=childInfo[i].maxOfVals;

        if(childInfo[i].minOfVals< minimum)
            minimum=childInfo[i].minOfVals;

    }

    info->maxOfVals=maximum;
    info->minOfVals=minimum;


    // we set the info->run value to false, so that the parrent thread of this thread will know that it is done
    info->run = false;

}

int main()
{
    ThreadInfo info;


    srand(time(NULL));
    double n=rand()%6+1;

    cout<<"n is: "<<n<<endl;

    // initializing thread info
    info.randomN=n;
    info.maxOfVals=n;
    info.minOfVals=n;
    info.level = 1;
    info.run = true;

   std::thread t(ChildWork, &info) ;
     t.join();

    while(info.run);

    info.maxOfVals= max<unsigned long>(info.randomN,info.maxOfVals);
    info.minOfVals= min<unsigned long>(info.randomN,info.minOfVals);

    cout << "Max is: " << info.maxOfVals <<" and Min is: "<<info.minOfVals;

}

The code compiles with no error, but when I execute it, it gives me this : 代码编译没有错误,但是当我执行它时,它给出了以下信息:

libc++abi.dylib: terminating with uncaught exception of type std::__1::system_error: thread constructor failed: Resource temporarily unavailable Abort trap: 6 libc ++ abi.dylib:以类型为std :: __ 1 :: system_error的未捕获异常终止:线程构造函数失败:资源暂时不可用中止陷阱:6

You spawn too many threads. 您产生了太多线程。 It looks a bit like a fork() bomb. 它看起来有点像fork()炸弹。 Threads are a very heavy-weight system resource. 线程是非常重的系统资源。 Use them sparingly. 谨慎使用它们。

Within the function void Childwork I see two mistakes: 在函数void Childwork我看到两个错误:

  1. As someone already pointed out in the comments, you check the info level of a thread and then you go and create some more threads regardless of the previous check. 正如有人已经在注释中指出的那样,您检查线程的信息级别,然后继续创建更多线程,而不管先前的检查如何。

  2. Within the for loop that spawns your new threads, you increment the info level right before you spawn the actual thread. 在产生新线程的for循环中,在产生实际线程之前立即增加信息级别。 However you increment a freshly created instance of ThreadInfo here ThreadInfo* childInfo = new ThreadInfo[(int)n] . 但是,您可以在此处增加一个新创建的ThreadInfo实例ThreadInfo* childInfo = new ThreadInfo[(int)n] All instances within childInfo hold a level of 0. Basically the level of each thread you spawn is 1. childInfo中的所有实例的级别均为0。基本上,您产生的每个线程的级别为1。

In general avoid using threads to achieve concurrency for I/O bound operations (*). 通常,避免使用线程来实现I / O绑定操作(*)的并发性。 Just use threads to achieve concurrency for independent CPU bound operations. 只需使用线程即可为独立的CPU绑定操作实现并发性。 As a rule of thumb you never need more threads than you have CPU cores in your system (**). 根据经验,您所需要的线程数永远不会超过系统中具有CPU内核(**)的线程数。 Having more does not improve concurrency and does not improve performance. 拥有更多内容不会提高并发性,也不会提高性能。

(*) You should always use direct function calls and an event based system to run pseudo concurrent I/O operations. (*)您应始终使用直接函数调用和基于事件的系统来运行伪并发I / O操作。 You do not need any threading to do so. 您不需要任何线程来执行此操作。 For example a TCP server does not need any threads to serve thousands of clients. 例如,TCP服务器不需要任何线程即可为数千个客户端提供服务。

(**) This is the ideal case. (**)这是理想的情况。 In practice your software is composed of multiple parts, developed by independent developers and maintained in different modes, so it is ok to have some threads which could be theoretically avoided. 实际上,您的软件由独立开发人员开发并由不同模式维护的多个部分组成,因此可以从理论上避免一些线程。

Multithreading is still rocket science in 2019. Especially in C++. 多线程在2019年仍然是火箭科学。尤其是在C ++中。 Do not do it unless you know exactly what you are doing. 除非您确切知道自己在做什么,否则不要这样做。 Here is a good series of blog posts that handle threads. 这是一系列处理线程的博客文章

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM