使用boost::condition\u变量进行线程同步 我正在做C++多线程的实验,我不知道如何解决一个问题。假设我们有线程池,它使用现有线程处理用户请求,并在没有可用线程的情况下创建新线程。我已经创建了命令队列线程安全类,它有push和pop方法。pop在队列为空时等待,并仅在命令可用或发生超时时返回。现在是实现线程池的时候了。这个想法是让空闲线程睡眠一段时间,如果在这段时间后没有什么事情可做,就杀死线程。这里是实现 command_queue::handler_t handler; while (handler = tasks.pop(timeout)) { handler(); }
这里,如果发生超时,我们将退出线程过程。这很好,但新线程的创建存在问题。假设我们已经有2个线程处理用户请求,它们目前正在工作,但我们需要异步执行其他一些操作。 我们叫 应该启动新线程,因为没有可用的空闲线程。当线程可用时,它调用使用boost::condition\u变量进行线程同步 我正在做C++多线程的实验,我不知道如何解决一个问题。假设我们有线程池,它使用现有线程处理用户请求,并在没有可用线程的情况下创建新线程。我已经创建了命令队列线程安全类,它有push和pop方法。pop在队列为空时等待,并仅在命令可用或发生超时时返回。现在是实现线程池的时候了。这个想法是让空闲线程睡眠一段时间,如果在这段时间后没有什么事情可做,就杀死线程。这里是实现 command_queue::handler_t handler; while (handler = tasks.pop(timeout)) { handler(); },c++,boost,threadpool,C++,Boost,Threadpool,这里,如果发生超时,我们将退出线程过程。这很好,但新线程的创建存在问题。假设我们已经有2个线程处理用户请求,它们目前正在工作,但我们需要异步执行其他一些操作。 我们叫 应该启动新线程,因为没有可用的空闲线程。当线程可用时,它调用timed\u waiton条件变量,因此检查是否有线程在等待 if (thread_are_free_threads) // ??? condition.notify_one(); else create_thread(thread_proc); 但是如何
timed\u wait
on条件变量,因此检查是否有线程在等待
if (thread_are_free_threads) // ???
condition.notify_one();
else
create_thread(thread_proc);
但是如何检查呢?文档中说,如果没有等待的线程,就什么也不做。如果我能检查一下它是否没有任何作用,那将是一个解决办法
if (!condition.notify_one()) // nobody was notified
create_thread(thread_proc);
据我所知,没有办法核实这一点
谢谢您的回答。您需要创建另一个变量(可能是一个信号量),该变量知道有多少线程正在运行,然后您可以在调用notify之前检查该变量并创建一个新线程(如果需要)
另一个更好的选择是,线程超时时不要退出。他们应该活着等待通知。不要在通知超时时退出,而是检查一个变量以查看程序是否仍在运行或是否正在“关闭”,如果程序仍在运行,则再次开始等待。更典型的线程池如下所示:
Pool::Pool()
{
runningThreads = 0;
actualThreads = 0;
finished = false;
jobQue.Init();
mutex.Init();
conditionVariable.Init();
for(int loop=0; loop < threadCount; ++loop) { startThread(threadroutine); }
}
Pool::threadroutine()
{
{
// Extra code to count threads sp we can add more if required.
RAIILocker doLock(mutex);
++ actualThreads;
++ runningThreads;
}
while(!finished)
{
Job job;
{
RAIILocker doLock(mutex);
while(jobQue.empty())
{
// This is the key.
// Here the thread is suspended (using zero resources)
// until some other thread calls the notify_one on the
// conditionVariable. At this point exactly one thread is release
// and it will start executing as soon as it re-acquires the lock
// on the mutex.
//
-- runningThreads;
conditionVariable.wait(mutex);
++ runningThreads;
}
job = jobQue.getJobAndRemoveFromQue();
}
job.execute();
}
{
// Extra code to count threads sp we can add more if required.
RAIILocker doLock(mutex);
-- actualThreads;
-- runningThreads;
}
}
Pool::AddJob(Job job)
{
RAIILocker doLock(mutex);
// This is where you would check to see if you need more threads.
if (runningThreads == actualThreads) // Plus some other conditions.
{
// increment both counts. When it waits we decrease the running count.
startThread(threadroutine);
}
jobQue.push_back(job);
conditionVariable.notify_one(); // This releases one worker thread
// from the call to wait() above.
// Note: The worker thread will not start
// until this thread releases the mutex.
}
Pool::Pool()
{
runningThreads=0;
实际读数=0;
完成=错误;
jobQue.Init();
mutex.Init();
conditionVariable.Init();
对于(int-loop=0;loop
我认为您需要重新考虑您的设计。在一个简单的模型中,庄家线程将工作分配给玩家线程,庄家将工作放入消息队列中,并让其中一个玩家在有机会时拿起工作
在您的情况下,经销商正在积极管理线程池,因为它保留了关于哪些播放器线程空闲,哪些线程繁忙的知识。因为经销商知道哪个玩家空闲,所以经销商可以主动地将空闲的任务传递给该玩家,并使用一个简单的信号量(或cond var)向该玩家发送信号-每个玩家有一个信号量。在这种情况下,经销商可以通过给线程一个kill-myve任务来主动销毁空闲线程 现在我找到了一个解决方案,但并不是那么完美。 我有一个名为free的易失性成员变量,它在池中存储空闲线程的数量
void thread_pool::thread_function()
{
free++;
command_queue::handler_t handler;
while (handler = tasks.pop(timeout))
{
free--;
handler();
free++;
}
free--;
}
当我将任务分配给线程时,我会执行如下操作
if (free == 0)
threads.create_thread(boost::bind(&thread_pool::thread_function, this));
同步仍然存在问题,因为如果上下文在释放后被切换——在
thread\u函数中
我们可能会创建一个新的线程,实际上我们并不需要它,但是由于任务队列是线程安全的,所以这没有问题,这只是一个不必要的开销。你能提出解决方案吗?你对此有何看法?也许最好让它保持原样,然后在这里再进行一次同步?另一个想法。您可以查询消息队列的长度。如果太长,请创建一个新的工作人员。你知道,用小注释编写代码通常比用少量代码编写英语要清晰得多。在一个块中发布完整的代码。boost::thread_group
可以简化后者,也就是说,您可以调用interrupt_all()
在等待时请求关闭。其想法是创建一个智能线程池,它不会让不必要的线程保持活动状态。因此,这不会解决问题,只会通过更改任务来避免问题:)
if (free == 0)
threads.create_thread(boost::bind(&thread_pool::thread_function, this));