У меня возникли проблемы с разрешением состояния гонки, которое возникает при получении блокировки. У меня есть большое вычисление, которое запускается асинхронно. Мне нужно, чтобы моя предыдущая синхронная задача завершилась до того, как начнется большая задача. Большая задача запускает и ожидает переменную условия, и в идеальном мире маленькие задачи уведомляют переменную условия, когда они выполнены. Моя проблема возникает из-за того, что большая задача запускается слишком рано, и маленькие задачи запускают переменную условия, которая еще не полностью инициализирована и, следовательно, фактически не запускается, в результате чего программа блокируется.
Я свел это к этому минимальному примеру.
Я бы предположил, что это общая проблема. Как я могу проверить, что моя условная переменная фактически получила мьютекс и заблокирована?
#include <QCoreApplication>
#include <QObject>
#include <QFuture>
#include <QtConcurrent/QtConcurrent>
#include <QFutureWatcher>
#include <QWaitCondition>
class workUnit: public QObject
{
Q_OBJECT
public:
workUnit(QObject *parent)
{
m = new QMutex();
m->lock();
w=new QWaitCondition();
}
QWaitCondition* w;
QMutex* m;
public slots:
void runMe()
{
w->wait(m);
m->unlock();
//perform long computation
}
};int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
workUnit* mUnit=new workUnit(&a);
QFutureWatcher<void> w;
QObject::connect(&w, SIGNAL(finished()), &a, SLOT(quit()));
QFuture<void> f = QtConcurrent::run(mUnit,&workUnit::runMe);
w.setFuture(f);
_sleep(1000);//with this delay it works, without the delay it doesn't
mUnit->w->wakeAll();//This would be triggered by another process
return a.exec();
}
Документация для QWaitCondition::wait
говорится, что:
Мьютекс должен быть изначально заблокирован вызывающим потоком.
Вы должны удалить m->lock();
от конструктора и положить его в runMe()
функционировать перед вызовом wait
,
Других решений пока нет …