QT 线程同步

文章介绍了线程同步的概念,解释了为什么在多线程环境下需要同步机制来避免数据混乱。使用QT中的QMutex类作为线程同步工具,确保对全局变量的写操作按顺序进行,避免并发冲突。在示例中,两个线程A和B分别添加字符到全局变量g_gbalWelcome,通过QMutex的锁机制保证线程A先执行,线程B后执行,实现了安全的串行写入。
摘要由CSDN通过智能技术生成

什么是线程同步?

线程同步指线程之间如何按照约定的先后次序执行。

为什么需要线程同步?

当我们有多个线程要同时访问一个变量或对象时,如果这些线程中既有读又有写操作时,就会导致变量值或对象的状态出现混乱,从而导致程序异常

QT 线程同步方法

(一)QMutex

QMutex类就像一把锁,在互斥量之前上锁(QMutex::lock()),然后在使用完互斥量之后解锁(QMutex::unlock()),如果一个线程试图向一个已经被其它线程上锁了互斥量上锁的话,这个线程将被阻塞(挂起),直到这个互斥量被解锁。

QMutex工程中线程a,b对同一个变量g_gbalWelcome写值

mythreada.h

#ifndef MYTHREADA_H
#define MYTHREADA_H

#include <QThread>
#include <QMutex>//提供线程间访问序列化,比如两个线程顺序操作同一个全局变量
#include <QDebug>
extern QMutex g_mutex;
extern QByteArray g_gbalWelcome;

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

signals:

};

#endif // MYTHREADA_H

 mythreada.cpp

#include "mythreada.h"

extern QMutex g_mutex;
extern QByteArray g_gbalWelcome;

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

}

void myThreadA::run()
{
    qDebug()<<"Thread A is starting"<<Qt::endl;//作用与"\n"换行类似

    g_mutex.lock();
    g_gbalWelcome +='W';
    sleep(2);
    g_gbalWelcome +='e';
    g_mutex.unlock();

    qDebug()<<"Thread A is exiting"<<Qt::endl;

}

mythreadb.h

#ifndef MYTHREADB_H
#define MYTHREADB_H

#include <QThread>
#include <QMutex>//提供线程间访问序列化,比如两个线程顺序操作同一个全局变量
#include <QDebug>
extern QMutex g_mutex;
extern QByteArray g_gbalWelcome;

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

signals:

};

#endif // MYTHREADB_H

mythreadb.cpp

#include "mythreadb.h"

//利用关键字extern,可以在一个文件中引用另一个文件中定义的变量或者函数
extern QMutex g_mutex;
extern QByteArray g_gbalWelcome;

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

}

void MyThreadB::run()
{
    qDebug()<<"Thread B is starting"<<Qt::endl;

    g_mutex.lock();
    g_gbalWelcome +="lcome";
    g_mutex.unlock();

    qDebug()<<"Thread B is exiting"<<Qt::endl;

}

widget.h

#ifndef WIDGET_H
#define WIDGET_H

#include <QWidget>
#include <QMutex>
#include "mythreada.h"
#include "mythreadb.h"
#include <QTimer>
QT_BEGIN_NAMESPACE
namespace Ui { class Widget; }
QT_END_NAMESPACE

extern QMutex g_mutex;
extern QByteArray g_gbalWelcome;//其声明的函数和变量可以在本模块或其它模块中使用

class Widget : public QWidget
{
    Q_OBJECT

public:
    Widget(QWidget *parent = nullptr);
    ~Widget();

private slots:
    void on_pushButton_clicked();
    void showResult();

private:
    Ui::Widget *ui;
    myThreadA *m_a;
    MyThreadB *m_b;
    QTimer *m_t;
};
#endif // WIDGET_H

widget.cpp

#include "widget.h"
#include "ui_widget.h"

QMutex g_mutex;
QByteArray g_gbalWelcome;

Widget::Widget(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::Widget)
{
    ui->setupUi(this);
    m_a=new myThreadA(this);
    m_b=new MyThreadB(this);
    m_t=new QTimer(this);
    m_t->setSingleShot(true);
    connect(m_t,SIGNAL(timeout()),this,SLOT(showResult()));

}

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


void Widget::on_pushButton_clicked()
{
    g_gbalWelcome.clear();

    m_a->start();
    m_b->start();
    m_t->start(2000);//2s
}

void Widget::showResult()
{
    qDebug()<<g_gbalWelcome<<Qt::endl;
    ui->textBrowser->setText(g_gbalWelcome);
}

运行界面如图

若红框中的内容不对。可把定时器的时间延长。采用QMutex互锁写的过程,使a进程完了b进程再开始写。

QMutex类参考:

(31条消息) Qt线程同步的几种方法_qt 异步线程_e5Max的博客-CSDN博客https://blog.csdn.net/e5Max/article/details/81703877

条件触发QWaitCondition

(31条消息) Qt线程:QWaitCondition_友善啊,朋友的博客-CSDN博客https://blog.csdn.net/kenfan1647/article/details/118636579

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值