Qt執行緒同步的幾種方法

2021-08-23 14:15:36 字數 2586 閱讀 2923

qmutex類就像一把鎖,在互斥量之前上鎖(qmutex::lock()),然後在使用完互斥量之後解鎖(qmutex::unlock())。比如下面的**:

void somemethod()

class thread1 : public qthread };

class thread2 : public qthread

};

如上面的**,在函式somemethod裡面有兩條語句,如果有兩個執行緒啟動之後,這兩個執行緒都將呼叫這個函式(run函式即為執行緒啟動後自動執行的函式),則可能會出現的結果是hello hello world world。但顯然,這並不是我們想要的,我們希望的是每個執行緒可以一次性執行完somemethod函式裡面的**。這個時候我們便可以在函式裡面給函式體加上鎖,然後在結束的時候解鎖。

這裡需要注意的是,如果乙個執行緒試圖向乙個已經被其它執行緒上鎖了互斥量上鎖的話,這個執行緒將被阻塞(掛起),直到這個互斥量被解鎖。如果乙個執行緒希望自己在試圖對乙個上鎖了的互斥量進行訪問的時候能夠不被阻塞(而是立即返回),可以將lock()函式替換為trylock()函式,這個函式的效果是:如果執行緒正在試圖訪問的互斥量已經被上鎖了,那麼可以立即返回而不被阻塞。

使用 qmutex 對互斥量進行加鎖解鎖比較繁瑣,在一些複雜的函式或者丟擲c++異常的函式中都非常容易發生錯誤。可以使用乙個方便的 qmutexlocker 類來簡化對互斥量的處理。首先,qmutexlocker類的建構函式接收乙個qmutex物件作為引數並且上鎖,然後在析構函式中自動對其進行解鎖。如下**:

qmutex mutex;

void somemethod()

這裡建立乙個qmutexlocker類例項,在這個例項的建構函式中將對mutex物件進行加鎖。然後在析構函式中自動對mutex進行解鎖。解鎖的工作不需要顯示地呼叫unlock函式,而是根據qmutexlocker物件的作用域繫結在一起了。

前兩種保護互斥量的方法比較絕對,其達到的效果是:不管我要對互斥量做些是什麼,我都要乙個人霸佔著,即使我只是看看它,也不能讓別人看。這會使得這個互斥量資源的使用率大大下降,造成資源等待等問題。

於是,我們可以對執行緒對互斥量的操作進行分類:讀和寫。有幾種情況:

1、如果我只是看看的話,你也可以看,大家看到的都是正確的結果;

2、如果我要看這個資料,你是不能改的,不然我看到的結果就不知道是什麼了;

3、我在改的時候,你不能看,否則我可能會讓你看到不正確的結果;

4、我在改的時候,你當然不能改了。

因此,我們可以對qmutex鎖進行公升級,將其公升級為qreadwritelock,qmutex加鎖的方法是lock(),而qreadwritelock鎖有兩種鎖法:設定為讀鎖(lockforread())和寫鎖(lockforwrite())。**如下:

qreadwritelock lock;

void somemethod()

於是可能有以下四種情況:

1、乙個執行緒試圖對乙個加了讀鎖的互斥量進行上讀鎖,允許;

2、乙個執行緒試圖對乙個加了讀鎖的互斥量進行上寫鎖,阻塞;

3、乙個執行緒試圖對乙個加了寫鎖的互斥量進行上讀鎖,阻塞;

4、乙個執行緒試圖對乙個加了寫鎖的互斥量進行上寫鎖,阻塞。

和qmutex與qmutexlocker類的關係類似,關於讀寫鎖也有兩個便利類,讀鎖和寫鎖,qreadlocker和qwritelocker。它們的建構函式都是乙個qreadwritelock物件,不同的是,在qreadlocker的建構函式裡面是對讀寫鎖進行lockforread()加鎖操作,而在qwritelocker的建構函式裡面是對讀寫鎖進行lockforwrite()加鎖操作。然後解鎖操作unlock()都是在析構函式中完成的。

void write()

void read()

qreadlocker和qwritelocker的成員函式都一模一樣,退出函式的時區域性變數locker會自動銷毀,講lock自動解鎖。也可以呼叫locker.unlock()給lock解鎖,然後再呼叫locker.relock()再鎖住lock。也可以呼叫locker.readwritelock()獲取建立locker時引入的那個lock的指標。

前面的幾種鎖都是用來保護只有乙個變數的互斥量的。但是還有些互斥量(資源)的數量並不止乙個,比如乙個電腦安裝了2個印表機,我已經申請了乙個,但是我不能霸佔這兩個,你來訪問的時候如果發現還有空閒的仍然可以申請到的。於是這個互斥量可以分為兩部分,已使用和未使用。乙個執行緒在申請的時候,會對未使用到的部分進行加鎖操作,如果加鎖失敗則阻塞,如果加鎖成功,即又有乙個資源被使用了,於是則將已使用到的部分解鎖乙個。

以著名的生產者消費者問題為例,分析問題:生產者需要的是空閒位置存放產品,結果是可取的產品多了乙個。於是,我們可以定義兩個訊號量:qsemaphore freespace和qsemaphore usedspace,前者是給生產者使用的,後者是給消費者使用的。

qwaitcondition最大的好處,我覺得,是能在乙個執行緒中喚醒乙個或多個其它執行緒,當然前提是,其它執行緒在等待某個qwaitcondition,否則不起作用,你喚醒也沒用。qwaitcondition必須與qmutex或者qreadwritelock一起用。

C 執行緒同步的幾種方法

幾種方法 我們在程式設計的時候,有時會使用多執行緒來解決問題,比如你的程式需要在後台處理一大堆資料,但還要使使用者介面處於可操作狀態 或者你的程式需要訪問一些外部資源如資料庫或網路檔案等。這些情況你都可以建立乙個子執行緒去處理,然而,多執行緒不可避免地會帶來乙個問題,就是執行緒同步的問題。如果這個問...

C 執行緒同步的幾種方法

我們在程式設計的時候,有時會使用多執行緒來解決問題,比如你的程式需要在後台處理一大堆資料,但還要使使用者介面處於可操作狀態 或者你的程式需要訪問一些外部資源如資料庫或網路檔案等。這些情況你都可以建立乙個子執行緒去處理,然而,多執行緒不可避免地會帶來乙個問題,就是執行緒同步的問題。如果這個問題處理不好...

C 執行緒同步的幾種方法

我們在程式設計的時候,有時會使用多執行緒來解決問題,比如你的程式需要在後台處理一大堆資料,但還要使使用者介面處於可操作狀態 或者你的程式需要訪問一些外部資源如資料庫或網路檔案等。這些情況你都可以建立乙個子執行緒去處理,然而,多執行緒不可避免地會帶來乙個問題,就是執行緒同步的問題。如果這個問題處理不好...