我试图在我的主应用程序中实现3个额外的线程,这些线程执行非共享操作。
起初我认为它正常工作,因为如果我取消注释WorkerThread函数中的最后一个printf调用,它会在一段随机时间后锁定在WaitThread()。如果没有printf,有时需要几秒钟才能锁定mWaitCond.Wait()函数,有时会在启动后立即执行。 printf似乎可以修复线程的时间。
应用程序没有崩溃,只是应用程序的cpu使用率为0%(和每个线程)并且没有响应。在visual studio调试器中停止显示在WaitThread()函数中的行(mWakeUp)mWaitCondition.Wait()作为当前位置。它还表明mWakeUp对于所有线程都是假的,因此它不应该保持在while循环中。
我的设计背后的想法:
可能是waitthread一个接一个地等待线程并且因为它等待让说在索引0的线程,索引2处的线程继续运行?
static const ui32 NumContexts = 3;
// array of pointers to threads
std::thread* mThreadHandles[NumContexts];
// wakup
std::atomic<bool> mWakeUp[NumContexts];
std::mutex mWakeMutex[NumContexts];
std::condition_variable mWakeCondition[NumContexts];
// wait for thread to finish task
std::mutex mWaitMutex[NumContexts];
std::condition_variable mWaitCondition[NumContexts];
// stop signal
std::atomic<bool> mStop[NumContexts];
void Framework::SetupThreading()
{
// create and start threads
for (int i = 0; i < NumContexts; i++)
{
this->mWakeUp[i] = false;
this->mStop[i] = false;
this->mThreadHandles[i] = new std::thread(&Framework::WorkerThread, this, reinterpret_cast<void*>(i));
}
}
//---------------------------------------------
void Framework::WakeUpThread(int i)
{
{
//auto lock = std::unique_lock<std::mutex>(this->mWakeMutex[i]);
std::lock_guard<std::mutex> lock(this->mWakeMutex[i]);
//printf("Waking up thread %i \n", i);
this->mWakeUp[i] = true;
}
this->mWakeCondition[i].notify_one();
}
// THIS FUNCTION LOCKS
//---------------------------------------------
void Framework::WaitThread(int i)
{
auto lock = std::unique_lock<std::mutex>(this->mWaitMutex[i]);
//printf("Waiting for thread %i to finish \n", i);
while (this->mWakeUp[i])
this->mWaitCondition[i].wait(lock);
//printf("Thread %i finished! \n", i);
}
//---------------------------------------------
void Framework::StopThread(int i)
{
auto lock = std::unique_lock<std::mutex>(this->mWakeMutex[i]);
printf("Sending stop signal for thread %i \n", i);
this->mStop[i] = true;
this->mWakeCondition[i].notify_one();
}
//---------------------------------------------
void Framework::JoinThread(int i)
{
printf("Waiting for join of thread %i \n", i);
this->mThreadHandles[i]->join();
printf("Thread %i joined! \n", i);
}
// THESE ARE CALLED IN THE MAIN LOOP
//---------------------------------------------
void Framework::WorkerInit()
{
for (int i = 0; i < NumContexts; i++)
{
this->WakeUpThread(i);
}
}
void Framework::WorkerWait()
{
for (int i = 0; i < NumContexts; i++)
{
this->WaitThread(i);
}
}
// THE FUNCTION CALLED BY THE THREADS
//---------------------------------------------
void Framework::WorkerThread(LPVOID workerIndex)
{
int threadIndex = reinterpret_cast<int>(workerIndex);
while (threadIndex < NumContexts && threadIndex >= 0)
{
{
auto lock = std::unique_lock<std::mutex>(this->mWakeMutex[threadIndex]);
//printf("thread %i: waiting for wakeup or stop signal...\n", threadIndex);
// not stopped nor woken up? continue to wait
while (this->mWakeUp[threadIndex] == false && this->mStop[threadIndex] == false)
{
this->mWakeCondition[threadIndex].wait(lock);
}
// stop signal sent?
if (this->mStop[threadIndex])
{
//printf("thread %i: got stop signal!\n", threadIndex);
return;
}
//printf("thread %i: got wakeup signal!\n", threadIndex);
// lock unlocks here (lock destructor)
}
// printf("thread %i: running the task...\n", threadIndex);
// RUN CODE HERE
//printf("thread %i finished! Sending signal!...\n", threadIndex);
// m_wakeup is atomic so there is no concurrency issue with wait()
this->mWakeUp[threadIndex] = false;
this->mWaitCondition[threadIndex].notify_all();
}
}
答案 0 :(得分:1)
如果线程的CPU使用率为零,则它不会在while循环中旋转,而是在wait()上被阻塞。在wait()取消阻塞之前,不会测试循环条件。
检查调试器中的调用堆栈以验证,暂停的位置可能只是指示您的源代码中的返回位置,而不是当前位置。
还要检查WorkerThread实例的状态 - 它们是否正在运行并调用notify_all()
?您的调试器线程是否可识别?
我不确定我是否理解你的设计或意图,但从表面看来它似乎有些过于复杂,并且已经成熟,可能会陷入僵局。