多线程相关知识点整理

内容:

    1 线程的概念

    2多线程的互斥控制方法

      QMutex类和QMutexLocker类

    3程的同步控制方法

     QSemaphore类和QWaitCondition类

1 线程简介

  线程是一种轻量级的进程,是程序执行流的最小单元,一个标准的线程由线程ID,当前指令指针,寄存器集合和堆栈组成。线程可由操作系统控制,也可由程序控制。它是进程的一部分,但它比进程更容易更快创建,也更容易撤销,在许多系统中创建一个县城较创建一个进程要块10-100倍。每个程序都有一个“主线程”,主线程在main()函数中执行。

  线程是程序中一个单一的顺序控制流程。在单个程序中同时运行多个线程完成不同的工作,称为多线程。

类:QThread

  QThread::QThread

 
  
(QObject* parent=0);    //构造函数

  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();
}
 
  



你可能感兴趣的:(笔记)