簡體   English   中英

提升線程拋出異常“thread_resource_error:資源暫時不可用”

[英]boost thread throwing exception “thread_resource_error: resource temporarily unavailable”

我有類似於以下代碼的代碼

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:資源暫時不可用Aborted

這個例外是什么意思? 任何想法都會有所幫助。

每個進程可以創建的線程數量有限制。

例如,在linux上,

cat /proc/sys/kernel/threads-max

告訴你當前的最大值。 默認值是內存頁數/ 4,因此在我的系統上它是513785,但在另一個盒子上可能要低得多。 例如,在我的郵件服務器盒(512mb RAM)上它只有7295。

你可以限制。 但事實上,這將是無用的,因為操作系統無法有效地安排它們。 所以,請嘗試使用線程池。

哦。 PS。 detach()他的線程有助於(很多)節省資源。 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;
        }
    }
}

首先,我沒有使用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(); 
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM