• Qt多线程同步总结


    1、QMutex

     
    QMutex mutex;
     
    void func()
    {
    mutex.lock();
    ........
    mutex.unlock();
    }
     
    在复杂函数或者异常处理中,对mutex进行lock()和unlock()操作将会很复杂,进入点要lock(),在所有跳出点都要unlock(),想想都蛋疼!忘记unlock()将是很苦逼的事情,所以Qt引进了QMutexLocker来避免lock()和unlock()操作。
     
    QMutex mutex;
     
    void complexFunc()
    {
    QMutexLocker locker(&mutex);//在函数需要的地方建立QMutexLocker对象,并把mutex指针传进来就好了,后面什么事情也不用做了,等到退出函数后,这个QMutexLocker对象局部变量会自己销毁,销毁了就解锁了。方便吧。当然,你也可以调用locker.unlock()给mutex解锁,然后再调用locker.relock()再锁住mutex。也可以调用locker.mutex()获取建立locker时引入的那个mutex的指针。是不是很方便?
    ..........
            ............
    }
     
    3、QReadWriteLock
    这个允许多个进程同时读,但是只有一个写。而且写读不能同时进行。
     
    QReadWriteLock lock;
     
    void write()
    {
    lock.lockForWrite();//为写而锁
    ..........
    lock.unlock();//解锁
    }
     
    void read()
    {
    lock.lockForRead();//为读而锁
    ..............
    lock.unlock();//解锁
    }
     
     
    这个有点类似于QMutex和QMutexLocker。也是为了避免那些复杂的lockForRead()/lockForWrite()和unlock()操作,要是程序流程复杂起来实在是很让人小心谨慎到蛋疼。但是联手QReadLocker和QWriteLocker后就不一样了。
    QReadWriteLock lock;
     
    void write()
    {
    QReadLocker locker(&lock);
    ..........
    }
     
    void read()
    {
    QWriteLocker locker(&lock);
    ..............
    }
     
     
    QReadLocker和QWriteLocker的成员函数都一模一样,退出函数的时局部变量locker会自动销毁,讲lock自动解锁。也可以调用locker.unlock()给lock解锁,然后再调用locker.relock()再锁住lock。也可以调用locker.readWriteLock()获取建立locker时引入的那个lock的指针。
     
    5、QSemaphore
     
    它的成员函数是
    QSemaphore ( int n = 0 )//建立对象时可以给它n个资源
    ~QSemaphore ()
    void acquire ( int n = 1 )// 这个操作一次减少n个资源,如果现有资源不到n个就会阻塞
    int available () const   //返回当前可用的QSemaphore资源个数
    void release ( int n = 1 )//这个操作一次增加n个资源
    bool tryAcquire ( int n = 1 )//类似于acquire,但是申请不到n个资源时不会阻塞会立即返回
    bool tryAcquire ( int n, int timeout )
     
    下面举生产者-消费者例子说明
     
     const int DataSize = 100000;//要生产的数据个数
     const int BufferSize = 8192;//用于盛数据的缓存大小
     char buffer[BufferSize];
     
    //要定义两个信号量,一个用于表示自由空间,一个用于表示已用空间
     QSemaphore freeBytes(BufferSize);//自由空间初始化大小当然等于缓存大小啦
     QSemaphore usedBytes;
     
    class Producer : public QThread
     {
     public:
         void run();
     };
     
     void Producer::run()
     {
         qsrand(QTime(0,0,0).secsTo(QTime::currentTime()));
         for (int i = 0; i < DataSize; ++i) {
             freeBytes.acquire();//申请一个自由空间,没有就阻塞
             buffer[i % BufferSize] = "ACGT"[(int)qrand() % 4];
             usedBytes.release();//已用空间增加一个,有货啦!
         }
     }
     
     
    class Consumer : public QThread
     {
     public:
         void run();
     };
     
     void Consumer::run()
     {
         for (int i = 0; i < DataSize; ++i) {
             usedBytes.acquire();
             fprintf(stderr, "%c", buffer[i % BufferSize]);
             freeBytes.release();
         }
         fprintf(stderr, " ");
     }
     
    int main(int argc, char *argv[])
     {
         QCoreApplication app(argc, argv);
         Producer producer;
         Consumer consumer;
         producer.start();
         consumer.start();
         producer.wait();
         consumer.wait();
         return 0;
     }
     
     
    QWaitCondition最大的好处,我觉得,是能在一个线程中唤醒一个或多个其它线程,当然前提是,其它线程在等待某个QWaitCondition,否则不起作用,你唤醒也没用。QWaitCondition必须与QMutex或者QReadwriteLock一起用。
  • 相关阅读:
    linux命令学习之:cd
    SSH原理与运用
    java遍历当前会话所有Session
    spring+quartz报错:Table 'XXXX.QRTZ_TRIGGERS' doesn't exist
    python检测编码
    python安装模块
    python网络爬虫
    系统编码 python编码
    python 中文路径
    python读取文件乱码
  • 原文地址:https://www.cnblogs.com/senior-engineer/p/7109710.html
Copyright © 2020-2023  润新知