我的代码类似于以下代码
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&gt;'的实例后终止调用 what():boost :: thread_resource_error:资源暂时不可用 中止
这个例外是什么意思?任何想法都会有所帮助。
答案 0 :(得分:8)
每个进程可以创建的线程数量有限制。
在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;
}
}
}
答案 1 :(得分:-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();
}