什么是线程同步?
线程同步指线程之间如何按照约定的先后次序执行。
为什么需要线程同步?
当我们有多个线程要同时访问一个变量或对象时,如果这些线程中既有读又有写操作时,就会导致变量值或对象的状态出现混乱,从而导致程序异常
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