Тупик с помощью переменных условия Boost; указатели не обновляются между потоками?

0

Я реализую приложение, которое использует протокол ввода-вывода. У меня есть три потока, одно чтение в данных (изображения), одно из них обрабатывает их и одно записывает обработанные образы обратно на диск.

Я столкнулся с тупиком с нитью читателя и потоком обработки. В потоках есть доступ к указателю, называемому toDeblur, который является указателем на последующее обработку изображения. Читательский поток читается на изображении, присваивает его указатель toDeblur, а затем уведомляет поток обработки, что toDeblur содержит изображение для обработки.

Соответствующий код для потока читателя выглядит следующим образом:

//Wait until it 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 наблюдается в потоке обработки?

EDIT: Я должен добавить, что приведенные выше фрагменты являются частью циклов, поэтому блокировки/ожидания происходят до каждого раунда чтения/обработки.

Результат, который я получаю от запуска программы, выглядит следующим образом:

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 и возвращается к ожиданию.

  • 0
    Подумайте об объявлении переменной как volatile чтобы компилятор не оптимизировал ее.
  • 0
    @AlexandruBarbarosie К сожалению, никакого эффекта. Проблема все еще происходит.
Показать ещё 1 комментарий
Теги:
multithreading
boost
condition-variable

3 ответа

0
Лучший ответ

Я решил проблему. Причина тупика заключается в том, что указатель toDeblur передавался потокам по значению, а не по ссылке, что, разумеется, означало, что когда поток читателя обновлял значение указателя, в отличие от указанного на нем объекта, это обновление не было отражено в копии указателя, который был обработан.

1

Почему бы не поставить очереди указателей изображений "deblur" с очередями производителей-потребителей? Возможно, вы можете контролировать поток с помощью фиксированного пула * deblur, созданного при запуске и удерживаемого в очереди пула.

Если обработка имеет более одного потока, вам может понадобиться номер последовательности в изображениях, чтобы гарантировать, что результат не выходит из строя.

0

У вас есть две условные переменные, разделяющие один замок/мьютекс, вам лучше сделать каждый условный переменный компаньон с независимой блокировкой/мьютексом. BTW, типичное использование одной условной переменной:

// 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, в противном случае высокая вероятность приведет к мертвой блокировке.

  • 0
    Хорошо, я изменил его, чтобы у каждого потока был свой мьютекс, а также условная переменная. К сожалению, это не решает проблему. Я должен добавить, что приведенные выше фрагменты кода являются частью циклов, поэтому блокировки / ожидания происходят перед каждым циклом чтения / обработки.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню