我正在实现一个使用IO管道的应用程序。我有三个线程,一个读取数据(图像),一个对它们进行处理,另一个将处理后的图像写回磁盘。
我遇到了读取器线程和处理线程的死锁。线程都可以访问一个名为toDeblur的指针,该指针指向下一个要处理的图像。读取器线程读取图像,将其指针分配给toDeblur,然后通知处理线程toDeblur包含用于处理的图像。
读取器线程的相关代码如下:
//Wait until it's okay to read again.
boost::unique_lock<boost::mutex> lock(*deblurLock);
while(toDeblur != NULL)
{
readCondition->wait(lock);
}
DeblurImage* read = readImage(is, fileName);
toDeblur = read;
cerr << "readImage notifying deblurCondition" << endl;
//Notify the processing thread(s) that an image is ready.
deblurCondition->notify_one();
以及处理线程:
//Wait for our condition variable.
boost::unique_lock<boost::mutex> lock(*deblurLock);
cerr << "processImage waiting for non-NULL image" << endl;
while(toDeblur == NULL)
{
cerr << "processImage waiting for deblurCondition variable" << endl;
deblurCondition->wait(lock);
}
readCondition->notify_one();
processImage(kernels, deblurP, toDeblur);
但是,我发现在运行这段代码时,我遇到了一个死锁,因为当被通知时,处理线程检查toDeblur是否为NULL,发现它是空的,然后回到睡眠状态,但是读取器线程在将一个有效的图像分配给toDeblur之后通知它。
我错过什么明显的东西了吗?我能做些什么来确保处理线程看到toDeblur的更新吗?
编辑:我应该补充一点,上面的片段是循环的一部分,所以锁/等待在每一轮读取/处理之前发生。
运行该程序的输出如下:
processImage waiting for non-NULL image
processImage waiting for deblurCondition variable
readImage is starting a read
readImage notifying deblurCondition
processImage waiting for deblurCondition variable
因此,processImage在收到通知后醒来,但看到toDeblur仍然为NULL,并返回等待。
发布于 2014-10-18 21:20:24
我已经解决了问题。死锁的原因是,toDeblur指针是通过值而不是引用传递给线程的,这当然意味着当读取器线程更新指针的值(而不是它所指向的对象)时,该更新没有反映在处理线程所拥有的指针的副本中。
发布于 2014-10-18 00:20:14
为什么不将“deblur”图像指针与生产者-消费者队列排队呢?您可以使用*deblur的固定池(在启动时创建并保存在池队列中)来控制它。
如果处理有多个线程,则可能需要图像中的序列号,以确保输出不会出错。
发布于 2014-10-17 18:39:25
您有两个条件变量共享一个锁/互斥,最好将每个条件变量与一个独立的锁/互斥体一起使用。顺便说一句,一个条件变量的典型用法是:
// wait
while(...){
boost::unique_lock<boost::mutex> lock(aMutex);
condVar->wait(lock);
}
// notify
{
boost::unique_lock<boost::mutex> lock(aMutex);
condVar->notify_one();
}
请确保在调用等待/通知后立即释放锁,否则,很有可能导致死锁。
https://stackoverflow.com/questions/26435602
复制相似问题