线程安全问题.
多线程程序太复杂了.
加锁
把多个线程要访问的公共资源,通过锁保护起来.=>把并发执行变成串行执行.
Linux mutex 互斥量.
C++11引入std::mutex
Qt 同样也提供了对应的锁,来针对系统提供的锁进行封装.QMutex
多个线程进行加锁的对象,得是同一个对象,不同对象,此时不会产生锁的互斥,也就无法把并发执行->串行执行,也就无法解决上述问题.
之前如果是并发执行,就可能第一个线程修改了一半,第二个线程也进行修改.就容易出现问题.(Linux 中详细介绍,++操作对应三个 cpu指令)
加了锁之后,第一个线程顺利拿到锁,继续执行++,在第一个线程没执行完的事后,第二个线程也尝试加锁,就会阻塞等待.一直等到第一个线程释放锁,第二个线程才能从阻塞中被唤醒.
没加锁两个线程对同一个变量++
thread.h
#ifndef THREAD_H
#define THREAD_H
#include<QThread>
#include<QMutex>
class Thread : public QThread
{
public:Thread();void run();static int num;static QMutex mutex;
};#endif // THREAD_H
widget.h
#ifndef WIDGET_H
#define WIDGET_H#include <QWidget>
#include"thread.h"
#include<QDebug>QT_BEGIN_NAMESPACE
namespace Ui { class Widget; }
QT_END_NAMESPACEclass Widget : public QWidget
{Q_OBJECTpublic:Widget(QWidget *parent = nullptr);~Widget();private:Ui::Widget *ui;
};
#endif // WIDGET_H
thread.cpp
#include "thread.h"
int Thread::num=0;
//QMutex Thread::mutex;
Thread::Thread()
{}
void Thread::run()
{for(int i=0;i<500000;i++){ // mutex.lock();num++;// mutex.unlock();}}
widget.cpp
#include "widget.h"
#include "ui_widget.h"Widget::Widget(QWidget *parent): QWidget(parent), ui(new Ui::Widget)
{ui->setupUi(this);Thread t1;Thread t2;t1.start();t2.start();t1.wait();t2.wait();qDebug()<<Thread::num;}Widget::~Widget()
{delete ui;
}
但是使用上面的锁的话,如果在加锁和解锁直接直接return ,或者抛异常的话,就会导致死锁问题
释放动态内存,也存在类似的问题,C++ 引入 智能指针就是解决上述问题的.
C++ 11 引入了std::lock guard,相当于是std::mutex智能指针,借助 RAII 机制.
std::lock_guard guard(mutex);
Qt 的锁和 C++ 标准库中的锁,本质上都是封装的系统提供的锁,编写多线程程序的时候,可以使用 Qt 的锁,也可以使用C++ 的锁.C++ 的锁能不能锁 Qt 的线程?也是可以的~~(虽然混着用也行,一般不建议)
qt实现: