zoukankan      html  css  js  c++  java
  • QT线程(二)---线程同步

     

    线程互斥

           多线程运行时,通常会访问同一个变量,同一个数据结构,或者同一段代码。因此,需要使用互斥技术来保护上述资源,确保多线程执行的正确性。

    注:

    我们通常说某个函数是线程安全的,也就是因为该函数实现加入了线程互斥保护。

           4.1、QMutex

     

    QMutex ( RecursionMode mode = NonRecursive )

     

    ~QMutex ()

    void

    lock ()

    mutex加锁,如果当前其他线程已对该mutex加锁了,则该调用被阻塞直到其他线程释放该mutex。

    bool

    tryLock ()

    mutex加锁,和lock不同的是,如果当前其他线程已对该mutex加锁了,则该调用会立即返回,而不被阻塞。

    bool

    tryLock ( int timeout )

    同tryLock,和tryLock不同的是,如果当前其他线程已对该mutex加锁了,则该调用会等待一段时间,直到超时或者其他线程释放了mutex。

    void

    unlock ()

    mutex解锁,释放被锁住的资源。

           Mutex有两种模式,用户可以在构造函数参数中指定。

          

    Constant

    Value

    Description

    QMutex::Recursive

    1

    In this mode, a thread can lock the same mutex multiple times and the mutex won't be unlocked until a corresponding number of unlock() calls have been made.

    该模式下,一个线程可以对mutex多次lock,直到相应次数的unlock,调用后,该mutex才真正被unlock。

    QMutex::NonRecursive

    0

    In this mode, a thread may only lock a mutex once.

    该模式下,mutex只能被lock一次。

    实例:

    QMutex mutex;
     int number = 6;
     
     void method1()
     {
         mutex.lock();
         number *= 5;
         number /= 4;
         mutex.unlock();
     }
     
     void method2()
     {
         mutex.lock();
         number *= 3;
         number /= 2;
         mutex.unlock();
     }

           4.1、QMutexLocker

     

    QMutexLocker ( QMutex * mutex )

     

    ~QMutexLocker ()

    QMutex *

    mutex () const

    void

    relock ()

    void

    unlock ()

           QMutexLocker实际上是对QMutex使用的一种简化。

    例如以下场景:

                  当某段代码存在多个分支,在对QMutex加锁后,需要在不同的分支路径下都执行解锁操作,才能保证Mutex关联的资源能被其他线程继续访问,       否则就出现死锁。

           QMutexLocker接收一个QMutex作为参数,当创建QMutexLocker对象时,就对关联的Mutex进行了Lock操作,直到该QMutexLocker对象被销毁,相关的QMutex才被Unlock。

    实例:

           直接使用QMutex:

    int complexFunction(int flag)
     {
         mutex.lock();
     
         int retVal = 0;
     
         switch (flag) {
         case 0:
         case 1:
             mutex.unlock();
             return moreComplexFunction(flag);
         case 2:
             {
                 int status = anotherFunction();
                 if (status < 0) {
                     mutex.unlock();
                     return -2;
                 }
                 retVal = status + flag;
             }
             break;
         default:
             if (flag > 10) {
                 mutex.unlock();
                 return -1;
             }
             break;
         }
     
         mutex.unlock();
         return retVal;
     }

    使用QMutexLocker:

    int complexFunction(int flag)
     {
         QMutexLocker locker(&mutex);
     
         int retVal = 0;
     
         switch (flag) {
         case 0:
         case 1:
             return moreComplexFunction(flag);
         case 2:
             {
                 int status = anotherFunction();
                 if (status < 0)
                     return -2;
                 retVal = status + flag;
             }
             break;
         default:
             if (flag > 10)
                 return -1;
             break;
         }
     
         return retVal;
     }

    当然,使用QMutexLocker时,也需要注意QMutexLocker对象的生存周期,否则可能会出现锁时间过长,或者锁住的资源过多。

    4.3、QReadLocker、QWriteLocker、QReadWriteLocker

           还有一种场景,我们所保护的资源是具有读写权限的,多个线程可以同时读取某个资源,但是当存在写操作,写操作未完成时,就不允许其他线程对该资源进行读操作。

     

    QReadWriteLock ()

     

    QReadWriteLock ( RecursionMode recursionMode )

     

    ~QReadWriteLock ()

    void

    lockForRead ()

    void

    lockForWrite ()

    bool

    tryLockForRead ()

    bool

    tryLockForRead ( int timeout )

    bool

    tryLockForWrite ()

    bool

    tryLockForWrite ( int timeout )

    void

    unlock ()

     

    QReadLocker ( QReadWriteLock * lock )

     

    ~QReadLocker ()

    QReadWriteLock *

    readWriteLock () const

    void

    relock ()

    void

    unlock ()

     

    QWriteLocker ( QReadWriteLock * lock )

     

    ~QWriteLocker ()

    QReadWriteLock *

    readWriteLock () const

    void

    relock ()

    void

    unlock ()

    实例:

    QReadWriteLock lock;
     
     void ReaderThread::run()
     {
         ...
         lock.lockForRead();
         read_file();
         lock.unlock();
         ...
     }
     
     void WriterThread::run()
     {
         ...
         lock.lockForWrite();
         write_file();
         lock.unlock();
         ...
     }

    4.4、QSemaphore

           和QMutex不同的是,QSemaphore一次可以对多个资源进行保护,

    例如以下场景:

           某工厂只有固定仓位,生产人员每天生产的产品数量不一,销售人员每天销售的产品数量也不一致。当生产人员生产P个产品时,就一次需要P个仓位,当销售人员销售C个产品时,就要求仓库中有足够多的产品才能销售。

    如果剩余仓位没有P个时,该批次的产品都不存入,当当前已有的产品没有C个时,就不能销售C个以上的产品,直到新产品加入后方可销售。

           这就是典型的生产者-消费者问题。

     

    QSemaphore ( int n = 0 )

     

    ~QSemaphore ()

    void

    acquire ( int n = 1 )

    int

    available () const

    void

    release ( int n = 1 )

    bool

    tryAcquire ( int n = 1 )

    bool

    tryAcquire ( int n, int timeout )

    实例:

    QSemaphore sem(5);      // sem.available() == 5   默认有5个产品
     
     sem.acquire(3);         // sem.available() == 2   销售3个产品,成功
     sem.acquire(2);         // sem.available() == 0  销售2个产品成功
     sem.release(5);         // sem.available() == 5  生产5个产品
     sem.release(5);         // sem.available() == 10 生产10个产品
     
     sem.tryAcquire(1);      // sem.available() == 9, returns true 消费1个产品,成功
     sem.tryAcquire(250);    // sem.available() == 9, returns false 企图销售250个产品,失败,因为当前只剩下14个产品

    4.5、QWaitCondition

  • 相关阅读:
    (转)js的左右滑动触屏事件
    (转)Document对象内容集合
    AppCan相关网站
    (转)iOS应用程序生命周期(前后台切换,应用的各种状态)详解
    (转)深入浅出 iOS 之生命周期
    (转)iphone数据存储之-- Core Data的使用
    (转)xcode5.0.2下国际化图文解说
    (转)IOS之Info.plist文件简介
    Note_Master-Detail Application(iOS template)_06_ YJYDetailViewController.h
    Note_Master-Detail Application(iOS template)_07_ YJYDetailViewController.m
  • 原文地址:https://www.cnblogs.com/lvdongjie/p/3944160.html
Copyright © 2011-2022 走看看