C++ “boost线程抛出异常”;线程“资源”错误:资源暂时不可用;

C++ “boost线程抛出异常”;线程“资源”错误:资源暂时不可用;,c++,multithreading,exception,boost,resources,C++,Multithreading,Exception,Boost,Resources,我有类似于以下代码的代码 boost::thread myThread unsigned char readbuffer[bignumber]; unsigned char writebuffer[bignumber]; for(int i=0; i<bignumber; ++i){ functiondostuff(); for(int j=0; j<2; ++j){ functiondomorestuff(); myThread = boost::thre

我有类似于以下代码的代码

boost::thread myThread
unsigned char readbuffer[bignumber];
unsigned char writebuffer[bignumber];

for(int i=0; i<bignumber; ++i){
  functiondostuff();
  for(int j=0; j<2; ++j){
    functiondomorestuff();
    myThread = boost::thread(&myClass::myFunction, this, j, i);
  }     
}
boost::线程读取
无符号字符读取缓冲区[bignumber];
无符号字符writebuffer[bignumber];

对于(inti=0;i,每个进程可以创建的线程数量有一个限制

例如,在linux上

cat /proc/sys/kernel/threads-max
告诉您当前的最大值。默认值是内存页数/4,因此在我的系统上是513785,但在另一个盒子上可能要低得多。例如,在我的邮件服务器盒子(512mb RAM)上,它只有7295

你可以限制它。但事实上,这是没有用的,因为操作系统无法有效地调度它们。因此,请尝试使用线程池

哦。PS.
detach()
-ing线程将有助于节约资源。
pthreads
可能会在达到操作系统限制之前阻止线程创建,因为它需要分配跟踪活动线程的开销。
detach
会释放这些线程(并删除程序退出前未连接所有线程的错误)

更新疯狂星期五奖励:一个线程池,可自动扩展到系统的内核数:

#include <boost/thread.hpp>
#include <boost/phoenix.hpp>
#include <boost/optional.hpp>

using namespace boost;
using namespace boost::phoenix::arg_names;

boost::atomic_size_t counter(0ul);

class thread_pool
{
  private:
      mutex mx;
      condition_variable cv;

      typedef function<void()> job_t;
      std::deque<job_t> _queue;

      thread_group pool;

      boost::atomic_bool shutdown;
      static void worker_thread(thread_pool& q)
      {
          while (auto job = q.dequeue())
              (*job)();
      }

  public:
      thread_pool() : shutdown(false) {
          for (unsigned i = 0; i < boost::thread::hardware_concurrency(); ++i)
              pool.create_thread(bind(worker_thread, ref(*this)));
      }

      void enqueue(job_t job) 
      {
          lock_guard<mutex> lk(mx);
          _queue.push_back(std::move(job));

          cv.notify_one();
      }

      optional<job_t> dequeue() 
      {
          unique_lock<mutex> lk(mx);
          namespace phx = boost::phoenix;

          cv.wait(lk, phx::ref(shutdown) || !phx::empty(phx::ref(_queue)));

          if (_queue.empty())
              return none;

          auto job = std::move(_queue.front());
          _queue.pop_front();

          return std::move(job);
      }

      ~thread_pool()
      {
          shutdown = true;
          {
              lock_guard<mutex> lk(mx);
              cv.notify_all();
          }

          pool.join_all();
      }
};

static constexpr size_t bignumber = 1 << 20;

class myClass 
{
    //unsigned char readbuffer[bignumber];
    //unsigned char writebuffer[bignumber];
    void functiondostuff() { }
    void functiondomorestuff() { }

    thread_pool pool; // uses 1 thread per core

  public:
    void wreak_havoc()
    {
        std::cout << "enqueuing jobs... " << std::flush;
        for(size_t i=0; i<bignumber; ++i)
        {
            functiondostuff();
            for(int j=0; j<2; ++j) {
                functiondomorestuff();
                pool.enqueue(bind(&myClass::myFunction, this, j, i));
            }     
        }
        std::cout << "done\n";
    }

  private:
    void myFunction(int i, int j)
    {
        boost::this_thread::sleep_for(boost::chrono::milliseconds(1));
        counter += 1;
    }
};

int main()
{
    myClass instance;
    instance.wreak_havoc();

    size_t last = 0;
    while (counter < (2*bignumber))
    {
        boost::this_thread::sleep_for(boost::chrono::milliseconds(100));
        if ((counter >> 4u) > last)
        {
            std::cout << "Progress: " << counter << "/" << (bignumber*2) << "\n";
            last = counter >> 4u;
        }
    }
}
#包括
#包括
#包括
使用名称空间boost;
使用名称空间boost::phoenix::arg_名称;
boost::原子大小计数器(0ul);
类线程池
{
私人:
互斥mx;
条件变量cv;
类型定义功能作业;
std::deque_队列;
线程组池;
原子弹爆炸关机;
静态无效工作线程(线程池和q)
{
while(自动作业=q.dequeue())
(*工作)();
}
公众:
线程池():关闭(false){
for(无符号i=0;i静态constexpr size\u t bignumber=1首先,我没有使用thread.join()或thread.detach()显式终止线程,因此线程总数将失控并引发异常

此外,在我的内部循环中,我创建了两个线程,但只保留了一个句柄。因此,我失去了对外部循环每次迭代1个线程的控制,导致线程总数增长超过了导致异常的线程的规定限制

为了保留在内部循环中创建的线程的唯一句柄,我将它们添加到boost::group中,并使用myGroup.join_all()。我想我也可以使用向量将句柄推到上面,然后将它们弹出以将它们全部连接起来

boost::thread_group myThreadGroup
unsigned char readbuffer[bignumber];
unsigned char writebuffer[bignumber];

for(int i=0; i<bignumber; ++i){
  functiondostuff();
  for(int j=0; j<2; ++j){
    functiondomorestuff();
    myThreadGroup.create_thread(boost::bind(&myClass::myFunction, this, i, j));
  }    
  functiondostuffagain();
  myThreadGroup.join_all(); 
}
boost::线程组myThreadGroup
无符号字符读取缓冲区[bignumber];
无符号字符writebuffer[bignumber];

对于(int i=0;i@deanresin在您的示例中,显然您正在同时创建
bignumer*2
线程(“如果您不
加入它们,它们就会打败您”)。您将它们分配给同一个变量(然后忘记这一点)没有什么不同。不管怎样,我正在添加一个
线程池
方法,因为这是疯狂的星期五:)@deanresin你为什么不/阅读/答案?不,它们不会完全消失。你至少需要
加入
分离
,否则它们/将/继续消耗资源。不管怎样,仅仅随意创建线程不会带来好的性能。如果你的应用程序是IO绑定的,你可能会在上每秒进行10k连接单线程(看看Boost Asio)。在这些情况下,学习异步!=并发。你没有“创建两个同名线程”。线程没有名称(是的,一些库为此添加了扩展)。线程就是这样。线程。你学习过指针吗?有点一样。你的线程变量只是“点”到线程资源(实际上,它为它抽象了特定于平台的句柄类型)。@StackedCrooked很好。这种类比被打破了,因为孩子们实际上会有相同的名字。线程没有这样的共同特征。它们只是碰巧被分配给同一
线程
变量一次(但从来没有同时分配过).所以,这更像是“如果你杀了一个男孩(你在一个特定的房子里遇到的男孩),那么所有住在同一个房子里的男孩都会被杀吗?”?没错。我想你已经知道了。不过,不要用向量替换线程组,因为你会得到错误的异常安全性。此外,RAII和
join\u all
本身应该足以成为使用该组的理由。从概念上讲,我同意:它只是一个线程容器。你仍然在随意创建线程。在我的框中,这仍然是通过ws
what():boost::thread\u resource\u error:resource暂时不可用
(这是一个内存为32GiB、线程限制为513785的框!)。这是空工作线程。演示Coliru上较小的
大\u数
的问题:添加
->分离()
“帮助”某种程度上,但线程仍在疯狂运行。例如,在我的重型计算机上运行'bignumber=1048576'需要43.8秒,平均运行约80个线程,一次达到170个线程。这真是糟糕透了。它要等到系统慢下来几毫秒,然后你就会迎面运行到同样的“资源不可用”状态砖墙