使用Boost条件变量的死锁;指针不在线程之间更新?

时间:2014-10-18 02:00:44

标签: c++ c multithreading boost condition-variable

我实现了一个使用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后通知它。

我错过了一些明显的东西吗?我能做些什么来确保处理线程能够看到Debllur的更新吗?

编辑:我应该补充一点,上面的片段是循环的一部分,因此锁定/等待在每轮读取/处理之前发生。

我从运行程序得到的输出如下:

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并返回等待。

3 个答案:

答案 0 :(得分:1)

为什么不用生产者 - 消费者队列排队'deblur'图像指针?您可以使用固定的* deblur池来控制它,在启动时创建并保存在池队列中。

如果处理有多个线程,则可能需要图像中的序列号以确保输出不会出现故障。

答案 1 :(得分:0)

你有两个条件变量共享一个锁/互斥锁,你最好使用一个独立的锁/互斥锁使每个条件变量伴随。顺便说一句,一个条件变量的典型用法是:

// wait    
while(...){
        boost::unique_lock<boost::mutex> lock(aMutex);
        condVar->wait(lock);
}

// notify
{
        boost::unique_lock<boost::mutex> lock(aMutex);
        condVar->notify_one();
}

确保在调用wait / notify后很快释放锁定,否则,很可能导致死锁。

答案 2 :(得分:0)

我已经解决了这个问题。死锁的原因是toDeblur指针是按值而不是通过引用传递给线程的,这当然意味着当读者线程更新指针的值时,而不是它指向的对象,该更新没有反映在处理线程的指针副本中。