首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >为什么互斥锁被解锁

为什么互斥锁被解锁
EN

Stack Overflow用户
提问于 2016-03-06 21:59:59
回答 2查看 121关注 0票数 1

我有这样的代码:

主窗h:

代码语言:javascript
运行
复制
namespace Ui {
    class MainWindow;
}

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

mainwindow.cpp:

代码语言:javascript
运行
复制
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;
}

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

代码语言:javascript
运行
复制
pure virtual method called
The program has unexpectedly finished.

我试过:

代码语言:javascript
运行
复制
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()。为什么会这样呢?我认为互斥锁必须将函数startProcess()锁定在on_calculateBtn_clicked()中,不应该发生任何事情。看来我不知道什么重要的事。事先谢谢您的建议。

EN

回答 2

Stack Overflow用户

发布于 2016-03-06 23:02:23

同一个互斥锁从同一个线程(包含事件循环的主线程)锁定两次,对非递归互斥无效。

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

但是,如果多次调用startProcess()并同时运行它,则必须为每个按下按钮启动一个线程,而要小心访问共享数据(很可能是使用互斥)--这才是真正的乐趣之源。

票数 0
EN

Stack Overflow用户

发布于 2016-03-07 07:46:42

我认为您(默认情况下)有一个Qt::DirectConnection与此按钮按下,对吗?即:

代码语言:javascript
运行
复制
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,那么在清除任务队列中的其他任务之前,它不会触发按下按钮。

但是..。天气是否好你的设计是好的是值得怀疑的,我认为你应该重新考虑你的策略(正如一些评论所建议的)。

编辑

哦,是的,意思是.为了回答你的问题,所以我不认为互斥开始两次解锁.这正是直接联系的本质。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/35833122

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档