QT線程(二)---線程同步

 

線程互斥html

       多線程運行時,一般會訪問同一個變量,同一個數據結構,或者同一段代碼。所以,須要使用互斥技術來保護上述資源,確保多線程執行的正確性。安全

注:數據結構

咱們一般說某個函數是線程安全的,也就是由於該函數實現加入了線程互斥保護。多線程

 

 

       4.一、QMutex函數

 

QMutex ( RecursionMode mode = NonRecursive )ui

 

~QMutex ()this

void.net

lock ()線程

mutex加鎖,若是當前其餘線程已對該mutex加鎖了,則該調用被阻塞直到其餘線程釋放該mutex。htm

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.一、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.三、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.四、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.五、QWaitCondition

相關文章
相關標籤/搜索