示例1:
如果不用锁,会发生什么呢?
参考:C++11多线程锁(入门)_c++线程加锁-CSDN博客
Widget::Widget(QWidget *parent) :
QWidget(parent),
ui(new Ui::Widget)
{
ui->setupUi(this);
qDebug()<<"main:"<<QThread::currentThreadId();
connect(this,SIGNAL(destroyed()),this,SLOT(quitThreadSlot()));
t=new try_thread(this);
t->start();
t1=new try_thread(this);
t1->start();
}
Widget::~Widget()
{
delete ui;
}
void Widget::quitThreadSlot()
{
t->quit();
t->wait();
t1->quit();
t1->wait();
}
为什么要quit() :回头看[2024/8/28]这段代码,发现不需要执行quit()函数
因为如果线程没有开启事件循环的话,该函数不起作用。
int counter=0;
try_thread::try_thread(QObject *parent) : QThread(parent)
{
}
void try_thread::run()
{
for(int i=0;i<100;i++)
{
counter++;
this->msleep(10); //每10ms休眠1次
qDebug()<<"son:"<<QThread::currentThreadId()<<" "<<counter;
}
}
输出结果:
main: 0x3948
son: 0x3ebc 2
son: 0x2140 2
son: 0x2140 4
son: 0x3ebc 4
son: 0x2140 6
son: 0x3ebc 6
son: 0x3ebc 8
son: 0x2140 8
son: 0x3ebc 10
son: 0x2140 10
son: 0x2140 12
son: 0x3ebc 12
son: 0x2140 14
son: 0x3ebc 14
son: 0x3ebc 16
son: 0x2140 16
son: 0x3ebc 18
son: 0x2140 18
son: 0x2140 20
son: 0x3ebc 20
son: 0x2140 22
son: 0x3ebc 22
son: 0x3ebc 24
son: 0x2140 24
son: 0x3ebc 26
son: 0x2140 26
son: 0x3ebc 28
son: 0x2140 28
son: 0x2140 30
son: 0x3ebc 30
son: 0x2140 32
son: 0x3ebc 32
son: 0x3ebc 34
son: 0x2140 34
son: 0x2140 36
son: 0x3ebc 36
son: 0x2140 38
son: 0x3ebc 38
son: 0x3ebc 40
son: 0x2140 40
son: 0x2140 42
son: 0x3ebc 42
son: 0x3ebc 44
son: 0x2140 44
son: 0x2140 46
son: 0x3ebc 46
son: 0x3ebc 48
son: 0x2140 48
son: 0x3ebc 50
son: 0x2140 50
son: 0x3ebc 52
son: 0x2140 52
son: 0x3ebc 54
son: 0x2140 54
son: 0x2140 56
son: 0x3ebc 56
son: 0x2140 58
son: 0x3ebc 58
son: 0x2140 60
son: 0x3ebc 60
son: 0x2140 62
son: 0x3ebc 62
son: 0x3ebc 64
son: 0x2140 64
son: 0x2140 66
son: 0x3ebc 66
son: 0x3ebc 68
son: 0x2140 68
son: 0x2140 70
son: 0x3ebc 70
son: 0x3ebc 72
son: 0x2140 72
son: 0x2140 74
son: 0x3ebc 74
son: 0x3ebc 76
son: 0x2140 76
son: 0x3ebc 78
son: 0x2140 78
son: 0x3ebc 80
son: 0x2140 80
son: 0x2140 82
son: 0x3ebc 82
son: 0x3ebc 84
son: 0x2140 84
son: 0x2140 86
son: 0x3ebc 86
son: 0x2140 88
son: 0x3ebc 88
son: 0x2140 90
son: 0x3ebc 90
son: 0x2140 92
son: 0x3ebc 92
son: 0x3ebc 94
son: 0x2140 94
son: 0x3ebc 96
son: 0x2140 96
son: 0x3ebc 98
son: 0x2140 98
son: 0x3ebc 100
son: 0x2140 100
son: 0x3ebc 102
son: 0x2140 102
son: 0x2140 104
son: 0x3ebc 104
son: 0x3ebc 106
son: 0x2140 106
son: 0x3ebc 108
son: 0x2140 108
son: 0x2140 110
son: 0x3ebc 110
son: 0x2140 112
son: 0x3ebc 112
son: 0x3ebc 114
son: 0x2140 114
son: 0x3ebc 116
son: 0x2140 116
son: 0x3ebc 118
son: 0x2140 118
son: 0x2140 120
son: 0x3ebc 120
son: 0x2140 122
son: 0x3ebc 122
son: 0x2140 124
son: 0x3ebc 124
son: 0x2140 126
son: 0x3ebc 126
son: 0x3ebc 128
son: 0x2140 128
son: 0x3ebc 130
son: 0x2140 130
son: 0x2140 132
son: 0x3ebc 132
son: 0x3ebc 134
son: 0x2140 134
son: 0x2140 136
son: 0x3ebc 136
son: 0x3ebc 138
son: 0x2140 138
son: 0x2140 140
son: 0x3ebc 140
son: 0x2140 142
son: 0x3ebc 142
son: 0x3ebc 144
son: 0x2140 144
son: 0x2140 146
son: 0x3ebc 146
son: 0x2140 148
son: 0x3ebc 148
son: 0x3ebc 150
son: 0x2140 150
son: 0x3ebc 152
son: 0x2140 152
son: 0x2140 154
son: 0x3ebc 154
son: 0x2140 156
son: 0x3ebc 156
son: 0x2140 158
son: 0x3ebc 158
son: 0x3ebc 160
son: 0x2140 160
son: 0x2140 162
son: 0x3ebc 162
son: 0x2140 164
son: 0x3ebc 164
son: 0x2140 166
son: 0x3ebc 166
son: 0x2140 168
son: 0x3ebc 168
son: 0x2140 170
son: 0x3ebc 170
son: 0x2140 172
son: 0x3ebc 172
son: 0x2140 174
son: 0x3ebc 174
son: 0x2140 176
son: 0x3ebc 176
son: 0x2140 178
son: 0x3ebc 178
son: 0x2140 180
son: 0x3ebc 180
son: 0x2140 182
son: 0x3ebc 182
son: 0x2140 184
son: 0x3ebc 184
son: 0x2140 186
son: 0x3ebc 186
son: 0x2140 188
son: 0x3ebc 188
son: 0x2140 190
son: 0x3ebc 190
son: 0x2140 192
son: 0x3ebc 192
son: 0x2140 194
son: 0x3ebc 194
son: 0x2140 196
son: 0x3ebc 196
son: 0x2140 198
son: 0x3ebc 198
son: 0x3ebc 200
son: 0x2140 200
counter是两个线程共用的变量。
过程是这样的:
son: 0x3ebc:counter++,变为1,休眠10ms
son: 0x2140:counter++,变为2,休眠10ms
然后就会输出:
son: 0x3ebc 2
son: 0x2140 2
上锁:
参考:
示例2:
int counter=0;
QMutex mutex;
try_thread::try_thread(QObject *parent) : QThread(parent)
{
}
void try_thread::run()
{
mutex.lock();
for(int i=0;i<10;i++)
{
counter++;
this->msleep(10);
qDebug()<<"son:"<<QThread::currentThreadId()<<" "<<counter;
}
mutex.unlock();
}
main: 0x4c28
son: 0x3be0 1
son: 0x3be0 2
son: 0x3be0 3
son: 0x3be0 4
son: 0x3be0 5
son: 0x3be0 6
son: 0x3be0 7
son: 0x3be0 8
son: 0x3be0 9
son: 0x3be0 10
son: 0x3640 11
son: 0x3640 12
son: 0x3640 13
son: 0x3640 14
son: 0x3640 15
son: 0x3640 16
son: 0x3640 17
son: 0x3640 18
son: 0x3640 19
son: 0x3640 20
上锁后的执行顺序:
son: 0x3be0:上锁,开始执行
for(int i=0;i<100;i++) { counter++; this->msleep(10); qDebug()<<"son:"<<QThread::currentThreadId()<<" "<<counter; }
解锁。
son: 0x3640:想要上锁,发现其他线程已经上锁了,就阻塞在这儿啦,等啊等啊,解锁了,
开始执行
for(int i=0;i<100;i++) { counter++; this->msleep(10); qDebug()<<"son:"<<QThread::currentThreadId()<<" "<<counter; }
然后解锁。
示例3:
改变锁的位置:
void try_thread::run()
{
for(int i=0;i<10;i++)
{
mutex.lock();
counter++;
this->msleep(10);
qDebug()<<"son:"<<QThread::currentThreadId()<<" "<<counter;
mutex.unlock();
}
}
输出结果:
main: 0x3ec4
son: 0x4c50 1
son: 0x4cd0 2
son: 0x4c50 3
son: 0x4cd0 4
son: 0x4c50 5
son: 0x4cd0 6
son: 0x4c50 7
son: 0x4cd0 8
son: 0x4c50 9
son: 0x4cd0 10
son: 0x4c50 11
son: 0x4cd0 12
son: 0x4c50 13
son: 0x4cd0 14
son: 0x4c50 15
son: 0x4cd0 16
son: 0x4c50 17
son: 0x4cd0 18
son: 0x4c50 19
son: 0x4cd0 20
示例4:QMutexLocker的使用
void try_thread::run()
{
for(int i=0;i<10;i++)
{
QMutexLocker locker(&mutex); //上锁
counter++;
this->msleep(10);
qDebug()<<"son:"<<QThread::currentThreadId()<<" "<<counter;
//执行完成后,locker被销毁,解锁
}
}
main: 0x4f84
son: 0x1dc8 1
son: 0x1df0 2
son: 0x1dc8 3
son: 0x1df0 4
son: 0x1dc8 5
son: 0x1df0 6
son: 0x1dc8 7
son: 0x1df0 8
son: 0x1dc8 9
son: 0x1df0 10
son: 0x1dc8 11
son: 0x1df0 12
son: 0x1dc8 13
son: 0x1df0 14
son: 0x1dc8 15
son: 0x1df0 16
son: 0x1dc8 17
son: 0x1df0 18
son: 0x1dc8 19
son: 0x1df0 20