Qt中的互斥锁(QMutex和QMutexLocker)

QMutex和QMutexLocker

  1. 类 QMutex 的主要函数有:
  • lock (); 加锁,如果该互斥锁被占用,该函数阻塞,直到互斥锁被释放。
  • unlock (); 解锁
  • bool tryLock (int timeout = 0);

表示尝试去加锁,timeout 为超时时间。如果互斥锁为可用状态,该函数会占用该互斥锁,并返回 true ,否则返回 false 。如果互斥锁被另一个线程占用,该函数会等待 timeout 毫秒直到互斥锁为可用状态。

  1. QMutexLocker 类的主要作用是用来管理 QMutex使用 QMutexLocker 的好处是,可以防止线程死锁。该对象在构造的时候加锁,析构的时候解锁。

使用场景

  • QMutex目的是保护一次只有一个线程访问一个对象、数据结构或一段代码。QMutex通常在较为简单的代码中使用,如果代码复杂最好使用【QMutexLocker+互斥锁】进行多线程同步,这样可以很容易确保锁定和解锁操作执行一致。

​ - 在复杂函数和语句或异常处理代码中lock和unlock QMutex很容易出错,而且很难调试。在这种情况下,可以使用QMutexLocker替代。

  • ​ QMutexLocker在一个需要锁定QMutex的函数中创建。当创建QMutexLocker时,互斥锁被锁定(后面可以使用unlock()和relock()对互斥锁进行解锁和重新锁定)。如果互斥锁锁定了,互斥对象将在QMutexLocker销毁时被解锁。
  • 即QMutexLocker创建时锁定,销毁时解锁,所以一般为局部变量

QMutex

预期:两个线程使用一把锁,操作一个数据,数据会被两个线程依次打印1.2.3.4…

MyThread.h

#ifndef MYTHREAD_H
#define MYTHREAD_H

#include <QThread>
#include <QMutex>

class MyThread : public QThread
{
    Q_OBJECT
public:
    explicit MyThread(QObject *parent = nullptr);
    void run();

private:

    static QMutex mutex;  // 多个线程使用一把锁
    static int num;       // 多个线程访问一个数据
};

#endif // MYTHREAD_H

MyThread.cpp

#include "mythread.h"
#include <QDebug>

QMutex MyThread::mutex;
int MyThread::num = 0;

MyThread::MyThread(QObject *parent) : QThread(parent)
{
}

void MyThread::run()
{

    while (1) {
        this->mutex.lock();// 加锁
        qDebug() << "Current Thread: " << this
                  << ", Value: " << this->num++;
        this->mutex.unlock();// 解锁


        QThread::sleep(1);// 线程睡眠两秒
    }
}

mainWindow.h

#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QMainWindow>
#include <QPainter>

namespace Ui {
class MainWindow;
}

class MainWindow : public QMainWindow
{
    Q_OBJECT

public:
    explicit MainWindow(QWidget *parent = 0);
    ~MainWindow();

private:
    Ui::MainWindow *ui;
};

#endif // MAINWINDOW_H

mainWindow.cpp

#include "mainwindow.h"
#include "ui_mainwindow.h"
#include "mythread.h"
#include <QDebug>
#include <QLabel>
#include <QFileInfo>
#include <QPushButton>
#include <QHBoxLayout>

MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
{
    ui->setupUi(this);

    MyThread *myThread1 = new MyThread(this);
    MyThread *myThread2 = new MyThread(this);
    myThread1->start();
    myThread2->start();

}
MainWindow::~MainWindow()
{
    delete ui;
}

运行结果:
在这里插入图片描述

QMutexLocker

预期:两个线程使用一把锁,操作一个数据,数据会被两个线程依次打印1.2.3.4…

  • 这里只改变了MyThread.cpp

MyThread.cpp

#include "mythread.h"
#include <QDebug>
#include <QMutexLocker>

QMutex MyThread::mutex;
int MyThread::num = 0;

MyThread::MyThread(QObject *parent) : QThread(parent)
{
}

void MyThread::run()
{

    while (1) {

        // QMutexLocker:创建的时候加锁,当QMutexLocker局部销毁的时候解锁
        {
            QMutexLocker lock(&this->mutex);
            qDebug() << "Current Thread: " << this
                      << ", Value: " << this->num++;
        }
        QThread::sleep(1);// 线程睡眠两秒
    }

}

运行结果:
在这里插入图片描述

  • 1
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
`QMutexLocker`是Qt的一个辅助类,用于简化互斥(`QMutex`)的使用。它可以自动管理互的上操作,确保在退出作用域时正确释放互斥,避免忘记解导致的死问题。 以下是`QMutexLocker`的基本用法示例: ```cpp #include <QCoreApplication> #include <QMutex> #include <QDebug> QMutex mutex; void workerFunction() { QMutexLocker locker(&mutex); // 创建QMutexLocker对象,并传入需要上互斥 qDebug() << "Start working..."; // 在这里执行需要互斥访问的代码 // ... qDebug() << "Finish working..."; // QMutexLocker析构函数会自动解互斥 } int main(int argc, char *argv[]) { QCoreApplication app(argc, argv); workerFunction(); return app.exec(); } ``` 在上述示例,我们创建了一个`workerFunction()`函数,函数内部的代码需要互斥访问。在函数内部,我们创建了一个`QMutexLocker`对象,并传入需要上互斥`mutex`。一旦创建了`QMutexLocker`对象,它会自动进行上操作。在函数执行结束时,`QMutexLocker`对象将会被销毁,析构函数会自动执行解操作。 通过使用`QMutexLocker`,我们可以简化互斥的上和解过程,确保正确地管理互斥,避免忘记解导致的问题。 需要注意的是,`QMutexLocker`是一个局部变量,它的生命周期受限于作用域。因此,它只适用于在局部范围内管理互斥。如果需要在更大的范围内使用互斥,请考虑使用其他方式进行管理。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值