当前位置:   article > 正文

QT 线程同步_qt中的线程同步

qt中的线程同步

什么是线程同步?

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

为什么需要线程同步?

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

QT 线程同步方法

(一)QMutex

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

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

mythreada.h

  1. #ifndef MYTHREADA_H
  2. #define MYTHREADA_H
  3. #include <QThread>
  4. #include <QMutex>//提供线程间访问序列化,比如两个线程顺序操作同一个全局变量
  5. #include <QDebug>
  6. extern QMutex g_mutex;
  7. extern QByteArray g_gbalWelcome;
  8. class myThreadA : public QThread
  9. {
  10. Q_OBJECT
  11. public:
  12. explicit myThreadA(QObject *parent = nullptr);
  13. void run();
  14. signals:
  15. };
  16. #endif // MYTHREADA_H

 mythreada.cpp

  1. #include "mythreada.h"
  2. extern QMutex g_mutex;
  3. extern QByteArray g_gbalWelcome;
  4. myThreadA::myThreadA(QObject *parent)
  5. : QThread{parent}
  6. {
  7. }
  8. void myThreadA::run()
  9. {
  10. qDebug()<<"Thread A is starting"<<Qt::endl;//作用与"\n"换行类似
  11. g_mutex.lock();
  12. g_gbalWelcome +='W';
  13. sleep(2);
  14. g_gbalWelcome +='e';
  15. g_mutex.unlock();
  16. qDebug()<<"Thread A is exiting"<<Qt::endl;
  17. }

mythreadb.h

  1. #ifndef MYTHREADB_H
  2. #define MYTHREADB_H
  3. #include <QThread>
  4. #include <QMutex>//提供线程间访问序列化,比如两个线程顺序操作同一个全局变量
  5. #include <QDebug>
  6. extern QMutex g_mutex;
  7. extern QByteArray g_gbalWelcome;
  8. class MyThreadB : public QThread
  9. {
  10. Q_OBJECT
  11. public:
  12. explicit MyThreadB(QObject *parent = nullptr);
  13. void run();
  14. signals:
  15. };
  16. #endif // MYTHREADB_H

mythreadb.cpp

  1. #include "mythreadb.h"
  2. //利用关键字extern,可以在一个文件中引用另一个文件中定义的变量或者函数
  3. extern QMutex g_mutex;
  4. extern QByteArray g_gbalWelcome;
  5. MyThreadB::MyThreadB(QObject *parent)
  6. : QThread{parent}
  7. {
  8. }
  9. void MyThreadB::run()
  10. {
  11. qDebug()<<"Thread B is starting"<<Qt::endl;
  12. g_mutex.lock();
  13. g_gbalWelcome +="lcome";
  14. g_mutex.unlock();
  15. qDebug()<<"Thread B is exiting"<<Qt::endl;
  16. }

widget.h

  1. #ifndef WIDGET_H
  2. #define WIDGET_H
  3. #include <QWidget>
  4. #include <QMutex>
  5. #include "mythreada.h"
  6. #include "mythreadb.h"
  7. #include <QTimer>
  8. QT_BEGIN_NAMESPACE
  9. namespace Ui { class Widget; }
  10. QT_END_NAMESPACE
  11. extern QMutex g_mutex;
  12. extern QByteArray g_gbalWelcome;//其声明的函数和变量可以在本模块或其它模块中使用
  13. class Widget : public QWidget
  14. {
  15. Q_OBJECT
  16. public:
  17. Widget(QWidget *parent = nullptr);
  18. ~Widget();
  19. private slots:
  20. void on_pushButton_clicked();
  21. void showResult();
  22. private:
  23. Ui::Widget *ui;
  24. myThreadA *m_a;
  25. MyThreadB *m_b;
  26. QTimer *m_t;
  27. };
  28. #endif // WIDGET_H

widget.cpp

  1. #include "widget.h"
  2. #include "ui_widget.h"
  3. QMutex g_mutex;
  4. QByteArray g_gbalWelcome;
  5. Widget::Widget(QWidget *parent)
  6. : QWidget(parent)
  7. , ui(new Ui::Widget)
  8. {
  9. ui->setupUi(this);
  10. m_a=new myThreadA(this);
  11. m_b=new MyThreadB(this);
  12. m_t=new QTimer(this);
  13. m_t->setSingleShot(true);
  14. connect(m_t,SIGNAL(timeout()),this,SLOT(showResult()));
  15. }
  16. Widget::~Widget()
  17. {
  18. delete ui;
  19. }
  20. void Widget::on_pushButton_clicked()
  21. {
  22. g_gbalWelcome.clear();
  23. m_a->start();
  24. m_b->start();
  25. m_t->start(2000);//2s
  26. }
  27. void Widget::showResult()
  28. {
  29. qDebug()<<g_gbalWelcome<<Qt::endl;
  30. ui->textBrowser->setText(g_gbalWelcome);
  31. }

运行界面如图

若红框中的内容不对。可把定时器的时间延长。采用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

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/天景科技苑/article/detail/865465
推荐阅读
相关标签
  

闽ICP备14008679号