【发布时间】:2015-01-30 15:29:08
【问题描述】:
我目前的问题是两个 QT 线程。其中一个发出信号以在第二个线程中开始操作,然后等待结果。一旦第二个线程完成,第一个线程应该使用来自第二个线程的结果继续其自己的操作。
为了让第一个线程休眠,我使用了 QMutex 和 QWaitCondition。第一个线程发出一个信号,然后在等待条件下休眠。但现在的问题是:如果第二个线程以某种方式比第一个线程更快,并且在第一个线程进入等待条件之前发出了 wakeAll() 调用,我就会卡住。我可以实现一个等待时间,但是我又不灵活了,如果第二个线程需要的时间比第一个线程等待的时间长,我又遇到了问题。
此问题已在此处解决:http://woboq.com/blog/qwaitcondition-solving-unavoidable-race.html,但他们决定不解决此问题。那么,有没有可能避免这种竞争条件?
补充:我不想把这个函数转换为第一个线程的函数,因为这个特定的函数应该可以同时从多个线程访问,而不会导致竞争条件。 IE。 Thread1 应该调用 Thread2 中的函数,等待完成,Thread3 也想调用该函数,但不允许这样做,它也必须等到完成。如果函数完成,Thread3 可以访问它。 (不止两个线程也是如此)。
示例函数:
这个函数应该发出信号,然后等待唤醒信号:
void Spectrometer_Control::moveStepper(int steps, bool dir)
{
emit stepperMoving();
qDebug() << "From Spectrometer_Control: Stepper should move in direction " + QString::number(dir) + " from position " + QString::number(MonoPos);
int newTarget = MonoPos + ((dir == true)?(steps):(-1 * steps));
qDebug() << "New target: " + QString::number(newTarget);
emit moveStepperToTarget(steps, dir);
qDebug() << "Locking WaitMutex!";
WaitMutex->lock();
qDebug() << "Waiting for signal!";
WaitForEngine->wait(WaitMutex);
WaitMutex->unlock();
qDebug() << "Finally unlocked!";
}
这个函数接收到调用,应该唤醒每个等待的函数:
void Stepper_Control_Worker::moveStepper(int steps, bool dir)
{
waitMutex->lock();
qDebug() << "Motor moved from down below!";
Stepper_Control_Worker::STP[1]->setValue((dir == true)?BlackLib::high:BlackLib::low);
usleep(50000);
Stepper_Control_Worker::STP[0]->setValue(BlackLib::low);
usleep(50000);
for(int i = 0; i < steps; i++)
{
Stepper_Control_Worker::STP[0]->setValue(BlackLib::high);
usleep(50000);
Stepper_Control_Worker::STP[0]->setValue(BlackLib::low);
}
WaitCond->wakeAll();
waitMutex->unlock();
emit StepperMoved(steps, dir);
}
第二个函数是“stepper_control”类的子成员(不能直接访问,只能通过访问)。步进控制器外部控件可以由多个函数使用,不仅是 Spectrometer_Control 中的函数 moveStepper,而且为了使事情更容易,我只添加了一个外部函数。但是在我不想让我的步进器感到困惑之后,我想如上所述限制访问。
【问题讨论】:
-
如果您只想让第一个线程休眠并等待第二个线程完成,为什么还要使用第二个线程?
-
因为我的第二个线程在另一个类中,也应该通过其他几种方式访问。把它放到这个类的一个函数中,就不可能在其他线程的其他函数中使用它,这也必须等待它。 (AFAIK,错了吗)?
-
线程不驻留在类中。 QThread 更像是一个线程控制器。从 QObject 派生的类可以移动到不同的线程。尽管如此,我仍然不明白为什么需要创建第二个线程。线程允许并发处理,(根据您的描述)您的应用程序没有使用它。如果您发布问题的示例代码,您可能会收到更好的响应,而缺少这可能是为什么有人(不是我)决定对您的问题投反对票的原因。
-
@Merlin069:这段代码是否应该完整且可运行?
-
理想情况下是的,但如果不是,只要是一个能清楚地描述问题的最小示例,就可以了。听起来您的问题更多是与类之间的通信有关的设计问题,而不是与线程有关的任何问题。
标签: c++ multithreading qt race-condition