线程在随机位置随机时间后停止运行,没有任何错误
Posted
技术标签:
【中文标题】线程在随机位置随机时间后停止运行,没有任何错误【英文标题】:Thread stops running after random time at random position without any error 【发布时间】:2017-09-06 13:16:16 【问题描述】:我有一个线程将图像作为原始数据转储到磁盘。它可以正常工作几分钟,然后突然停止执行任何操作。
通过命令行输出,我发现它在循环中的随机位置停止。
程序不会在这个线程中崩溃(它在线程停止运行后不久崩溃,因为我的图像缓冲区已满),所以线程中没有错误/异常/任何东西。
这是我的代码草图:
class ImageWriter
public:
// constructor, destructor
void continueWriting();
private:
void writeImages();
std::thread m_WriterThread;
bool m_WriterThreadRunning;
std::mutex m_ThreadRunningMutex;
ImageManager * m_ImageManager;
;
ImageWriter::continueWriting()
// whenever a new image is acquired, this function is called
// so if the thread has finished, it needs to be restarted
// this function is also used for the first start of writing
m_ThreadRunningMutex.lock();
if ( m_WriterThreadRunning )
m_ThreadRunningMutex.unlock();
else
m_ThreadRunningMutex.unlock();
if( m_WriterThread.joinable() )
m_WriterThread.join();
m_WriterThreadRunning = true;
m_WriterThread = std::thread( &ImageWriter::writeImages, this );
void ImageWriter::writeImages()
while ( true )
// MyImage is a struct that contains the image pointer and some metadata
std::shared_ptr< MyImage > imgPtr = m_ImageManager->getNextImage(m_uiCamId);
if( imgPtr == nullptr )
// this tells the ImageWriter that currently there are no further images queued
break;
// check whether the image is valid. If it's not, skip this image and continue with the next one
[...]
// create filename
std::stringstream cFileNameStr;
cFileNameStr << [...];
std::ofstream cRawFile( cFileNameStr.str().c_str(), std::ios::out | std::ios::binary );
unsigned char * ucDataPtr = imgPtr->cImgPtr;
if( cRawFile.is_open() )
// calculate file size
unsigned int uiFileSize = [...];
cRawFile.write(reinterpret_cast<char*>(ucDataPtr), uiFileSize);
cRawFile.close();
// dump some metadata into a singleton class for logging
[...]
m_ThreadRunningMutex.lock();
m_WriterThreadRunning = false;
m_ThreadRunningMutex.unlock();
ImageManager 是一个负责图像采集和对采集的图像进行排队的类。它还触发 continueWriting()。 continueWriting() 机制是必要的,因为图像的写入速度可能比获取图像的速度快。
为什么这个线程在随机位置随机停止运行并且没有任何错误?
Valgrind 不会在我的控制范围内产生任何东西。 我尝试设置线程的优先级,但这没有任何区别。 我也尝试了另一个磁盘,但这也没有任何区别。
【问题讨论】:
我不明白你在互斥锁下读了 m_WriterThreadRunning 并写了 false,但写了 true 不受保护?这个互斥锁只是为了保护一个布尔值吗?改用原子。我不会停止/启动线程 - 但会在队列中没有图像时实现一些等待机制,并且 continueWriting 只会向线程发出停止等待的信号。 写入 m_WriterThreadRunning true 发生在旧线程连接之后和新线程启动之前,因此不会发生竞争条件。等待机制是有意义的。我什至没有想到。即使它不能解决问题,它也应该更具可读性,真是个好主意! 症状:1) 多线程。 2) 显式使用互斥锁。 3) 短时间使用后的锁。诊断:排除任何合理怀疑,您处于死锁状态。 如果发生死锁,线程不会停在m_ThreadRunningMutex.lock();
吗?
【参考方案1】:
我注意到您立即解锁了两个分支中的线程。由于您所做的只是读取布尔值,因此您可能应该完全避免使用锁。读取通常不是需要同步的操作(除非它有副作用,例如读取流,或者位置被释放等)
请考虑:您永远不会在该 bool 为真之前从该 bool 读取 True 值,并且由于您所做的只是读取,因此您永远不会冒该函数为该 bool 分配不正确值的风险。在您已经加入您的线程之前,您不会在此处为 bool 分配新值。
我假设这里发生的情况是您的代码锁定了互斥锁,并且另一个线程尝试写入它,但由于它被锁定而无法写入。
【讨论】:
以上是关于线程在随机位置随机时间后停止运行,没有任何错误的主要内容,如果未能解决你的问题,请参考以下文章