在无限循环中,Std::thread在随机时间后锁定
std::thread locks after a random time in an endless loop
我试图实现3个额外的线程到我的主应用程序做非共享操作。
起初我认为它的工作,因为如果我取消注释在WorkerThread函数中的最后一个printf调用,它不会在WaitThread()随机一段时间后锁定。如果没有printf,有时需要几秒钟才能锁定mWaitCond.Wait()函数,有时是在启动之后。Printf似乎修复了线程的计时问题。
应用程序不会崩溃,只是应用程序的cpu使用率变为0%(以及每个线程)并且它没有响应。停止在visual studio调试器中显示行while(mWakeUp) mWaitCondition.Wait()在WaitThread()函数中作为当前位置。它还显示mWakeUp对所有线程都是false,所以它不应该停留在while循环中。
我的设计理念:
- SetupThreads()在进入主循环之前被调用 在无尽循环中,WorkerInit()被调用来唤醒线程
- 在访问3个线程的数据之前,调用WorkerWait()等待,直到它们完成
- 在WorkerThread函数中(由每个线程调用),我锁定互斥锁并等待直到线程被唤醒或停止
- 处理完数据后,wakeUp设置为false, condition_variable通知
可能是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();
}
}
如果线程的CPU使用率为零,则它在while循环中没有旋转,而是在wait()中阻塞。直到wait()解除阻塞,循环条件才会被测试。
检查调试器中的调用堆栈以验证,停止的位置可能只是指示您的源代码中的返回位置,而不是当前位置。
还要检查WorkerThread实例的状态-它们是否正在运行并调用notify_all()
?你的调试器线程感知吗?
我不确定我是否理解您的设计或意图,但从表面上看,它似乎有点过于复杂,并且已经成熟到陷入僵局的地步。
相关文章:
- C++为构建时间获取QDateTime的可靠方法
- 从持续时间构造std::chrono::system_clock::time_point
- 如何找到锁定Linux futex的C++行
- 向量 <int> a {N, 0} 和 int arr a[N] = {0} 的时间复杂度有什么区别
- while循环中while循环的时间复杂度是多少
- G锁定铸造到基础上会释放模拟行为
- 使用简单类型列表实现的指数编译时间.为什么
- 是否可以在编译时初始化数组,以便在运行时不会花费时间?
- 在已经使用Git的情况下减少编译时间
- 有没有一种方法可以创建一个带有哈希表的数据库,该哈希表具有恒定时间查找功能
- 如何将包含epoch时间的十六进制字符串转换为time_t
- 从文本文件中读取时钟时间和事件时间并进行处理
- 具有未知值时的时间复杂性
- 如何减少花费的时间
- C++在变量给定的指定时间内关闭电脑
- rcpp函数中的清理时间很长
- C++:floor unix时间戳到UTC月份
- 将线程锁定很长时间
- 为什么这个经过的时间(帧时间)计算会锁定我的游戏
- 在无限循环中,Std::thread在随机时间后锁定