线程在随机时间随机位置后停止运行,没有任何错误

时间:2017-09-06 13:16:17

标签: c++ multithreading mutex ofstream stdthread

我有一个将图像作为原始数据转储到磁盘的线程。它可以正常工作几分钟然后突然停止做任何事情。

通过命令行输出我发现它在循环内的随机位置停止。

程序在这个线程中没有崩溃(它在线程停止运行后不久崩溃,因为我的图像缓冲区已满),所以线程中没有错误/异常/任何内容。

这是我的代码草图:

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()机制是必要的,因为图像的写入速度可能比获取的速度快。

为什么这个线程在随机位置随机停止运行且没有任何错误?

瓦尔格林德并没有在我的控制范围内产生任何东西。 我尝试设置线程的优先级,但这并没有任何区别。 我也尝试了另一个磁盘,但这也没有任何区别。

1 个答案:

答案 0 :(得分:0)

我注意到你立刻解锁了两个分支中的线程。既然你所做的只是阅读布尔,你可能应该完全避免使用锁。读取通常不是需要同步的操作(除非它有副作用,例如读取流,或者取消分配位置等)

考虑一下:在真实之前你永远不会从那个bool中读取一个True值,并且因为你所做的只是读取,你将永远不会冒这个函数给那个bool赋值不正确的风险。在您加入线程之前,您不会在此处为bool分配新值。

我假设这里发生的事情是你的代码锁定了互斥锁,而另一个线程试图写入它,但是因为它被锁定了所以不能。