我有以下代码:
主线程通知工作线程启动/停止某个作业。在主线程中,触发器是一些UI按钮(在这种情况下是Qt SDK):
void PlaySlot(bool checked){
boost::unique_lock<boost::mutex> lock(m_mutex);
if(checked == true){
m_isPlayMode = true;
m_event.notify_one(); //tell thread to start playing.
}else{
m_isPlayMode = false;
}
}
现在,在工作线程中,一旦 m_isPlayMode 变为真,一些循环开始运行一段有限的时间,它将在时间结束时退出或 m_isPlayMode 变得虚假。
在线程操作符内:
while(true)
{
boost::unique_lock<boost::mutex> lock(m_mutex);
m_event.wait(lock); //wait for next event
if(m_isPlayMode == true){
while(m_frameIndex< totalFrames && m_isPlayMode){
m_frameIndex++;
///do some work
}
m_isPlayMode = false;
emit playEnded(false);
}
}
现在,在循环开始播放之后发生了什么,当PlaySlot()通过&#39;检查&#39; = false它没有更新m_isPlayMode并且程序没有响应。我怀疑条件竞争问题,因为我试图锁定已经锁定在线程循环中的互斥锁。
我通过从 PlaySlot 方法移除 unique_lock 并将m_isPlayMode转换为原子变量来解决它。它可以工作。
但我想知道两件事:
这样的解决方案是否有任何危险。
可以用另一种方式解决吗?
答案 0 :(得分:1)
请注意m_isPlayMode
受同一个互斥锁保护,因此在工作程序运行时无法更新。使用两个单独的互斥体,或原子。
编辑快速修复可能会添加第二个互斥锁:
void PlaySlot(bool checked){
boost::unique_lock<boost::mutex> lock(m_isPlayModeMutex); // <--
// ...
}
工作线程:
for (;;) {
boost::unique_lock<boost::mutex> lock(m_mutex);
m_event.wait(lock); // wait for next event
boost::unique_lock<boost::mutex> playModeLock(m_isPlayModeLock);
if(m_isPlayMode == true){
while(m_frameIndex< totalFrames && m_isPlayMode){
playModeLock.unlock();
/// ... (not locked here)
playModeLock.lock();
}
m_isPlayMode = false;
emit playEnded(false);
}
}