gpt4 book ai didi

c++ - std::thread 在无限循环中的随机时间后锁定

转载 作者:行者123 更新时间:2023-11-28 06:07:12 27 4
gpt4 key购买 nike

我正在尝试为我的主应用程序实现 3 个额外的线程来执行非共享操作。

起初我认为它可以工作,因为如果我取消注释 WorkerThread 函数中的最后一个 printf 调用,它不会在随机时间后锁定在 WaitThread()。如果没有 printf,有时需要几秒钟才能锁定 mWaitCond.Wait() 函数,有时刚开始就锁定。 printf 似乎修复了线程的时间。

应用程序没有崩溃,只是应用程序的 cpu 使用率变为 0%(和每个线程)并且它没有响应。在 visual studio 调试器中停止显示 WaitThread() 函数中的行 while(mWakeUp) mWaitCondition.Wait() 作为当前位置。它还表明 mWakeUp 对于所有线程都是假的,所以它不应该停留在那个 while 循环中。

我的设计理念:

  1. 在进入主无限循环之前调用 SetupThreads()
  2. 在无限循环中,调用WorkerInit()唤醒线程
  3. 在我访问 3 个线程的数据之前,调用 WorkerWait() 等待它们完成
  4. 在 WorkerThread 函数(由每个线程调用)中,我锁定互斥量并等待线程被唤醒或停止
  5. 处理数据后,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++ - std::thread 在无限循环中的随机时间后锁定,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32164854/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com