Qt之多线程(六)

来源:互联网 发布:windows 引导修复 编辑:程序博客网 时间:2024/05/18 00:27



一、pthread线程函数库

1.1 概述Linux下的线程函数库Windows下没有因此使用pthread函数的程序,只能在Linux下运行。比较:Qt下,有自己的多线程机制----QThread类下的run函数----子线程入口函数而Qt是跨平台的,所以使用QThread类的程序,能在Linux下、Windows下运行(但注意,是源码级的跨平台,仍然需要在各自的平台下编译)1.2 查询当前线程的 线程id号使用pthread_self()函数,返回值为pthread_t类型的 线程id号1.3 建立子线程的函数pthread_create()有4个参数:1、是线程id的地址,用来保存新建立的 线程id号,因此是 输出参数2、线程属性,使用默认值NULL即可3、子线程的入口函数,需要填写1个函数名。 函数名可以任意,如run,但参数必须是void *,返回值类型也必须是void *1.4 线程同步----使用mutex互斥量使用步骤:1、定义1个全局变量mutex,并赋值pthread_mutex_t mutex=PTHREAD_MUTEX_INITIALIZER;2、当子线程读写 共享资源(如火车票)时,先加锁3、读写完毕后,尽量早点 解锁----为了让其它线程运行时,可以得到锁代码:----2个线程,同时买火车票的例子#include <QtCore/QCoreApplication>#include <pthread.h>#include <unistd.h>pthread_mutex_t mutex=PTHREAD_MUTEX_INITIALIZER;//定义并初始化1个锁mutex 注意是全局变量int ticket=100;//共享资源 100张火车票void * run(void *arg)//子线程的入口函数----注意 函数名是可以任意定的;但参数、返回值类型必须是void *{ for(int i=0;i<50;i++) { pthread_mutex_lock(&mutex);//加锁,使用函数pthread_mutex_lock,参数是锁的地址 if(ticket==0) { break; } printf("tid %u ticketNum %d\n",pthread_self(),ticket); ticket--; pthread_mutex_unlock(&mutex);//解锁,使用函数pthread_mutex_unlock,参数是锁的地址 usleep(2000);//睡眠函数,单位是微妙;而且会导致cpu先运行其它线程;需要头文件unistd.h } return NULL;}int main(int argc, char *argv[]){ //QCoreApplication a(argc, argv); //pthread_t tid=pthread_self(); //printf("main tid is %u\n",tid); pthread_t tid2=0; pthread_t tid3=0; pthread_create(&tid2,NULL,run,NULL);//建立线程,注意将新的线程id号,赋值给了tid3 pthread_create(&tid3,NULL,run,NULL); sleep(3);//sleep函数,单位是秒;而且会导致cpu先运行其它线程,间接保证了main函数不要退出太早。sleep需要头文件unistd.h return 0; //return a.exec();}1.5 当前线程开始等待,直到等待的另外1个线程退出,然后当前线程才能继续向下运行pthread_join函数 ----有上述功能注意:利用该函数,在main函数中,可以不使用sleep了

二、哲学家就餐问题---考察对线程死锁的理解

描述:有4个哲学家一起吃饭,大家围成一圈;但每个哲学家之间都只有1个筷子。哲学家要不停得休息、吃饭;吃饭时,要依次拿自己2侧的筷子,如果拿不到,就死等;休息时,要依次放下左右2侧的筷子。提示:1、建立4个线程,模拟4个哲学家不停的吃饭、休息2、建立4个锁,对应了4个筷子,线程要通过对 不同的锁 加锁/解锁 来决定是否可以吃上饭代码://主界面的cpp文件#include "eat001widget.h"#include "ui_eat001widget.h"#include "persona.h"#include "personb.h"#include "personc.h"#include "persond.h"QMutex mutex1;//建立了4个锁,模拟了4个筷子QMutex mutex2;QMutex mutex3;QMutex mutex4;Eat001Widget::Eat001Widget(QWidget *parent) : QWidget(parent), ui(new Ui::Eat001Widget){ ui->setupUi(this);}Eat001Widget::~Eat001Widget(){ delete ui;}void Eat001Widget::on_pushButton_clicked()//点击界面上的按钮后,4个线程开始工作{ PersonA * personA=new PersonA; PersonB * personB=new PersonB; PersonC * personC=new PersonC; PersonD * personD=new PersonD; personA->start(); personB->start(); personC->start(); personD->start();}//PersonA类的h文件#ifndef PERSONA_H#define PERSONA_H#include <QtCore>class PersonA : public QThread{public: PersonA(); void run();};#endif // PERSONA_H//PersonA类的cpp文件#include "persona.h"extern QMutex mutex1;extern QMutex mutex4;PersonA::PersonA(){}void PersonA::run(){ while(true) { mutex1.lock();//代表取1号筷子 qDebug()<<"A +1"; msleep(1); mutex4.lock();//代表取4号筷子 qDebug()<<"A +4"; qDebug()<<"A is eatting";//取到2个筷子,才能吃饭 mutex4.unlock();//代表放下4号筷子 qDebug()<<"A -1"; mutex1.unlock();//代表放下1号筷子 qDebug()<<"A -4"; //wait(1); msleep(1);//等待1毫秒后,又去取筷子、吃饭 } return;}void PersonB::run(){ while(true) { mutex1.lock(); qDebug()<<"B +2"; mutex2.lock(); qDebug()<<"B +1"; qDebug()<<"B is eatting"; mutex1.unlock(); qDebug()<<"B -2"; mutex1.unlock(); qDebug()<<"B -1"; //wait(1); msleep(1); } return;}void PersonC::run(){ while(true) { mutex2.lock(); qDebug()<<"C +3"; mutex3.lock(); qDebug()<<"C +2"; qDebug()<<"C is eatting"; mutex3.unlock(); qDebug()<<"C -3"; mutex2.unlock(); qDebug()<<"C -2"; //wait(1); msleep(1); } return;}void PersonD::run(){ while(true) { mutex3.lock(); qDebug()<<"D +4"; mutex4.lock(); qDebug()<<"D +3"; qDebug()<<"D is eatting"; mutex4.unlock(); qDebug()<<"D -4"; mutex3.unlock(); qDebug()<<"D -3"; //wait(1); msleep(1); } return;}分析:----死锁问题要顺序加锁、反序解锁,否则可能会出现死锁而且加锁时,都是先加序号小的锁,再加序号大的锁




0 0
原创粉丝点击