为什么mutex已被解锁

时间:2016-03-06 21:59:59

标签: c++ multithreading qt mutex

我有这段代码:

mainwindow.h:

namespace Ui {
    class MainWindow;
}

class MainWindow : public QMainWindow {
private:
    QMutex mutex;
}

mainwindow.cpp:

void MainWindow::on_calculateBtn_clicked() {
    QMutexLocker locker(&mutex);
    qDebug() << "mutex has been locked" << endl;
    ui->calculateBtn->setEnabled(false);

    startProcess(); // huge calcutations

    ui->calculateBtn->setEnabled(true); // performed before startProcess() has finished (why?)
    qDebug() << "mutex will be unlocked" << endl;
}

如果我在startProcess()尚未完成时再次单击calculateBtn,我的程序崩溃了:

pure virtual method called
The program has unexpectedly finished.

我试过了:

void MainWindow::on_calculateBtn_clicked() {
    if (!processing) {
        processing = true;
        ui->calculateBtn->setEnabled(false);

        startProcess();

        ui->calculateBtn->setEnabled(true);  // performed before startProcess() has finished (why?)
        processing = false;
    }
}

没有共享数据,我只想在其他startProcess()完成之前不会启动一个startProcess()。 为什么会这样?我认为互斥锁必须在on_calculateBtn_clicked()中锁定函数startProcess(),并且不会发生任何事情。看来我不知道任何重要的事情。提前感谢任何建议。

2 个答案:

答案 0 :(得分:0)

相同的互斥锁从同一个线程(包含事件循环的主线程)被锁定两次,这对non-recursive mutex无效。

但即使是递归的互斥锁也无法解决代码的基本问题;你需要一个标志来表明你已经在进行计算,并在运行时从你对方法的所有后续调用返回,否则你将在同一个线程中多次启动它们,一个中断另一个,可能是糟糕的结果。更方便的是,在方法运行时禁用按钮并注意不要通过其他方式调用。

但是,如果多次调用startProcess()并同时运行它,则必须为每个按键启动一个线程,并注意以访问共享数据(最常见的是使用互斥体) - 这真正的乐趣开始了。

答案 1 :(得分:0)

我认为你(默认情况下)按下这个按钮就有一个Qt :: DirectConnection,对吗?即:

connect(..., SIGNAL(...),
        ..., SLOT(:on_calculateBtn_clicked()), <by-default-Qt::DirectConnection>);

我在这里看到的问题是按下第一个按钮会立即运行函数void MainWindow::on_calculateBtn_clicked() ....到目前为止,这是好的,互斥锁被锁定并且正在运行大量计算。

然而,当您再次按下按钮时,void MainWindow::on_calculateBtn_clicked()将再次立即运行(如中断)。它首先要做的是尝试锁定互斥锁,它必须挂在这里。

如果您连接到插槽void MainWindow::on_calculateBtn_clicked() Qt :: QueuedConnection,则它不会触发按钮按下,直到它清除其任务队列中的其他任务为止。

但....天气与否你的设计在这里很好是值得怀疑的,我想你应该重新思考你的策略(正如一些评论所暗示的那样)

修改

哦,是的,意味着要添加.....来回答你的问题,因此我不认为互斥锁开始被解锁两次......它只是直接连接的本质