一个QThread代表了一个在应用程序中可以独立控制的线程,它与进程中的其他线程分享数据,但是是独立执行的,QThread从run()函数开始执行,默认run()通过exec()来开启事件循环,并在线程内运行一个Qt事件循环。要创建一个线程,需要子类化QThread,并重新实现run()函数。
问题来了,多线程并发执行的时候,共享数据的准确性是不确定的。。。
解决方法:给共享数据加一把锁。
QMutex提供了一个互斥锁(mutex),在任何时间至多有一个线程可以获得mutex,如果一个线程尝试获得mutex,而mutex此时已被锁住,则这个线程会睡眠,直到现在获得mutex的线程对mutex对其解锁为止。互斥锁常用于对共享数据的访问进行保护。
完整代码如下:
"mythread.h"头文件
1 #ifndef MYTHREAD_H 2 #define MYTHREAD_H 3 4 #include <QObject> 5 #include<QThread> 6 7 class myThread : public QThread 8 { 9 public: 10 myThread(QObject*parent=nullptr); 11 void stop(); 12 protected: 13 void run() override;//需要对run()函数进行重写 14 private: 15 bool m_isStop; 16 }; 17 18 #endif // MYTHREAD_H
1 #include "mythread.h" 2 #include<QMutex> 3 #include<QDebug> 4 int gNum=0; 5 QMutex mutex; 6 myThread::myThread(QObject*parent):QThread(parent) 7 { 8 m_isStop=false; 9 } 10 11 void myThread::stop() 12 { 13 m_isStop=true; 14 } 15 16 void myThread::run() 17 { 18 int i=0; 19 while(!m_isStop&&i++<10000){ 20 mutex.lock();//处理共享数据前先加互斥锁,确保不会发生意想不到的结果(切记要加锁) 21 qDebug()<<QString::fromLocal8Bit("第%1天啦").arg(++gNum); 22 mutex.unlock();//处理完之后解锁,供其他线程使用 23 } 24 }
1 class Widget : public QWidget 2 { 3 Q_OBJECT 4 5 public: 6 Widget(QWidget *parent = nullptr); 7 ~Widget(); 8 9 private slots: 10 void on_startBtn_clicked(); 11 12 void on_stopBtn_clicked(); 13 14 private: 15 Ui::Widget *ui; 16 myThread m_thread1,m_thread2,m_thread3;//3个线程 17 };
1 void Widget::on_startBtn_clicked() 2 { 3 m_thread1.start();//启动线程 4 m_thread2.start(); 5 m_thread3.start(); 6 } 7 8 void Widget::on_stopBtn_clicked() 9 { 10 m_thread1.stop(); 11 m_thread2.stop(); 12 m_thread3.stop(); 13 }
运行结果如下(姑且不考虑样式):