【问题标题】:recursive threading with C++ gives a Resource temporarily unavailable使用 C++ 的递归线程使资源暂时不可用
【发布时间】:2019-01-16 08:02:02
【问题描述】:

所以我正在尝试创建一个程序,该程序实现一个生成随机数 (n) 并基于 n 创建 n 个线程的函数。主线程负责打印叶子的最小值和最大值。 Main线程的层次结构深度为3。

我已经写了下面的代码:

#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;

}

代码编译没有错误,但是当我执行它时,它给了我这个:

libc++abi.dylib:以未捕获的类型异常终止 std::__1::system_error:线程构造函数失败:资源 暂时不可用中止陷阱:6

【问题讨论】:

  • 看起来你在没有检查递归深度的情况下生成了新线程。
  • 这比n 线程创建了更多的地狱。 if(info-&gt;level &gt; 3) { info-&gt;run = false; } 之后的所有内容不应该在合格的else 或其他一些显式替代代码路径中吗?无关,srand 应该在每个进程执行时调用 一次,而不是每个线程启动一次。
  • 你应该提高并发编程的基础。您正在使用 bool 来验证一侧线程的终止,并加入刚刚在另一侧创建的线程(这违背了目的)。您应该使用 thread.join() 等待线程,而不是布尔值
  • 为什么要分离线程,然后明确检查它们是否正在运行,而不是将它们保存在集合中并加入它们?
  • 您可以将main 中的 spawn-and-join 替换为普通函数调用。

标签: c++ multithreading recursion


【解决方案1】:

你产生了太多的线程。它看起来有点像fork() 炸弹。线程是一个非常重量级的系统资源。谨慎使用它们。

在函数void Childwork 中我看到两个错误:

  1. 正如有人在 cmets 中已经指出的那样,您检查线程的信息级别,然后您去创建更多线程,而不管之前的检查如何。

  2. 在生成新线程的 for 循环中,在生成实际线程之前增加信息级别。但是,您在这里增加一个新创建的ThreadInfo 实例ThreadInfo* childInfo = new ThreadInfo[(int)n]。 childInfo 中的所有实例的级别均为 0。基本上,您生成的每个线程的级别为 1。

通常避免使用线程来实现 I/O 绑定操作的并发性 (*)。只需使用线程来实现独立的 CPU 绑定操作的并发性。根据经验,您需要的线程数永远不会超过系统中的 CPU 内核数 (**)。拥有更多不会提高并发性,也不会提高性能。

(*) 您应该始终使用直接函数调用和基于事件的系统来运行伪并发 I/O 操作。您不需要任何线程来执行此操作。例如,TCP 服务器不需要任何线程来服务数千个客户端。

(**) 这是理想情况。实际上,您的软件由多个部分组成,由独立开发人员开发并以不同的模式维护,因此可以有一些理论上可以避免的线程。

多线程在 2019 年仍然是火箭科学。尤其是在 C++ 中。除非您确切知道自己在做什么,否则不要这样做。这是一个处理线程的good series of blog posts

【讨论】:

  • @Bruno:谢谢!
猜你喜欢
  • 1970-01-01
  • 2018-05-11
  • 1970-01-01
  • 2017-11-18
  • 1970-01-01
  • 2014-01-22
  • 1970-01-01
  • 1970-01-01
  • 2021-02-21
相关资源
最近更新 更多