boost线程抛出异常“thread_resource_error:资源暂时不可用”

2024-02-17

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

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);
  }     
}

myFunction 从缓冲区读取并写入另一个缓冲区。它永远不会写入写入缓冲区中的同一位置。我在这里对线程做了一些根本性的错误吗?循环使用相同线程名称的线程创建是否不好?它运行了一段时间,然后我得到以下异常。

抛出 'boost::exception_detail::clone_impl >' 实例后调用终止 What(): boost::thread_resource_error: 资源暂时不可用 中止

这个异常是什么意思?任何想法都会有帮助。


每个进程可以创建的线程数是有限制的。

以Linux为例,

cat /proc/sys/kernel/threads-max

告诉你当前的最大值。默认值是内存页数/4,所以在我的系统上它是 513785,但在另一个机器上它可能要低得多。例如。在我的邮件服务器盒子(512mb RAM)上只有 7295。

你可以达到极限。但实际上这毫无用处,因为操作系统无法有效地调度它们。因此,请尝试使用线程池。

Oh. PS. detach()-ing 他线程will帮助(很多)节约资源。pthreads可能会在达到操作系统限制之前阻塞线程创建,因为它需要分配跟踪活动线程的开销。detach释放它们(并消除在程序退出之前未加入所有线程的错误)。

UPDATE疯狂星期五奖励:一个线程池,可以自动缩放到您系统拥有的核心数量:

#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;
        }
    }
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

boost线程抛出异常“thread_resource_error:资源暂时不可用” 的相关文章

随机推荐