内容:
1 线程的概念
2多线程的互斥控制方法
QMutex类和QMutexLocker类
3程的同步控制方法
QSemaphore类和QWaitCondition类
1 线程简介
线程是一种轻量级的进程,是程序执行流的最小单元,一个标准的线程由线程ID,当前指令指针,寄存器集合和堆栈组成。线程可由操作系统控制,也可由程序控制。它是进程的一部分,但它比进程更容易更快创建,也更容易撤销,在许多系统中创建一个县城较创建一个进程要块10-100倍。每个程序都有一个“主线程”,主线程在main()函数中执行。
线程是程序中一个单一的顺序控制流程。在单个程序中同时运行多个线程完成不同的工作,称为多线程。
类:QThread
QThread::QThread
void QThread::start(); //启动线程,启动线程里面的run();
bool QThread::wait(unsigned long time = ULONG_MAX);//阻塞调用该函数的线程,等待时间永不超时
void QThread::terminate(); //结束线程
2 多线程的互斥控制方法之QMutex类
多个线程访问一个类的私有成员,其结果是不可预知的。有些类的私有变量是临界资源。临界资源一次仅允许被一个线程使用,它可以是一块内存、一个数据结构、一个文件或其它具有排它性的东西。在程序中通常竞争使用临界资源。必须互斥执行的代码段称为临界区。为了阻止问题产生,临界区一次只能有一个线程进入,要实现这种功能就需要相关的机制管理线程的“进入”或“离开”。可以实现这种功能的类有QMutex、QMutexLocker。
类:QMutex
QMutex.lock(); //锁定互斥量
QMutex::unlock() ; //解锁互斥量
QMutex::tryLock(); //尝试锁定互斥量,如果锁定成功,返回true,否则返回false
例如:class Print
{
public:
Print() { i=0;}
void printf() { mutex.lock();++i;qDebug()<
private:
int i;
QMutex mutex;
};
类QMutexLocker
简化互斥量处理,在构造函数接收一个QMutex对象作为参数将其锁定,在解析函数中解锁这个互斥量。
class Print
{
public:
Print() { i=0;}
void printf() {mutexLocker locker(&mutex);++i;qDebug()<
private:
int i;
QMutex mutex;
};
locker 是局部变量,会在函数退出时结束其作用域,从而对互斥量mutex解锁。3 多线程同步控制方法之QSemaphore
类:QSemaphore提供一个通用的计数信号量,它是一个泛化的锁,互斥量只能锁定一次,信号量可以获取多次,信号量一般用于保护一定数量的同种资源,可用来解决生产者消费者问题。
QSemaphore sem(5); //创建一个有5个可用资源的信号量,此时sem.available==5;
sem.available(); //获取可用资源的数量
sem.acquire(2); //2个可用资源被用,此时sem.available==3;
sem.release(1); //释放1个可用资源,此时sem.available==4;
sem.tryAcquire(1); //尝试获取一个资源,获取成功,返回true;此时sem.available==3;
sem,tryAcquire(10); //获取失败,返回false,此时sem.available==3;
假如有五个座位,座位就是可用资源,这时来了两个人,占去两个座位,即sem.acquire(2),其中一个人离开了,释放了一个资源.即sem.release(1);这时还有四个座位可用,如果来了五个人,只有等待直到前面的哪一个人走了,他们才可以坐,就是sem.tryAcquire(5).
(2) 多线程控制方法之QWaitCondition类,为同步线程提供一个可用的条件。,可用来解决生产者消费者问题。
可通过设定wait条件、mutex和一个用来计数的int型对象来达到线程同步,先生产后消费的目的。
example:创建一个控制台应用
#include
#include
#include
#include
#include
QWaitCondition fullBuffer; //定义两个条件
QWaitCondition emptyBuffer;
const int DataSize = 100; //需要生产的资料的数量
const int BufferSize = 80; //定义缓存区的大小
int bufer[BufferSize];
int usedNumber = 0; //可用资料的数量
class Producer : public QThread //生产者线程类
{
public:
Producer();
void run();
};
Producer::Producer()
{
}
void Producer::run() //重写run()函数
{
for(int i=0;i{
QMutex mutex;mutex.lock();
if(usedNumber==BufferSize) //判断可用资源的数量是否占满缓存区emptyBuffer.wait(&mutex); //如果占满缓存区,该线程被阻塞,直到有可用空间条件成立,同时为互斥量解锁
bufer[i%BufferSize]=(i%BufferSize); //用缓冲区单元序列号给这个单元赋值
++usedNumber; //可供消费的资源数量加1
fullBuffer.wakeAll(); //唤醒消费者线程
mutex.unlock();
}
}class Consumer : public QThread //消费者线程类{public:
Consumer();void run();};Consumer::Consumer()
{}void Consumer::run(){int j=0;forever{
QMutex mutex;mutex.lock();
if(usedNumber==0) //阻塞fullBuffer.wait(&mutex); //等待有可用资源条件成立,还行该线程
printf("bufer[%d]=%d\n",j,bufer[j%BufferSize]);//打印该缓冲区的内容j=(++j)%BufferSize; //变量j循环加1
--usedNumber;
emptyBuffer.wakeAll();
mutex.unlock();
}
}int main(int argc, char *argv[]){QCoreApplication a(argc, argv);Producer producer;Consumer consumer;producer.start(); //启动线程,启动run();
consumer.start();
producer.wait(); //停止
consumer.wait();
return a.exec();}