QT 多執行緒

2021-10-24 23:53:13 字數 4239 閱讀 2328

1.1 程序

1.2 執行緒

1.3 執行緒與執行緒的區別聯絡

除了上面概念中所提到的,還有:

在乙個應用程式(程序)中同時執行多個小的部分(執行緒),這就是多執行緒。多個執行緒雖然共享一樣的資料,但是卻執行不同的任務。

併發是指在同乙個時間裡cpu同時執行兩條或多條命令。單核cpu和c++11以前實現的併發一般是偽併發。但隨著多核cpu的普及,c++11開始支援真正意義上的併發。

c++11可以通過多執行緒實現併發,這是一種比較底層、傳統的實現方式。c++11引入了5個頭檔案來支援多執行緒程式設計:////

#include // c++11 原子操作,限制併發程式對共享資料的使用,避免資料競爭#include // 該標頭檔案主要宣告了std::thread類,另外std::this_thread命名空間也在該標頭檔案中#include // c++11 互斥量mutex。在多執行緒環境中,有多個執行緒競爭同乙個公共資源,就很容易引發執行緒安全的問題#include // c++11 併發程式設計 主要包含了與條件變數相關的類和函式
是c++標準程式庫中的乙個標頭檔案,定義了c++11標準中一些互斥訪問的類與方法。

其中std::mutex表示普通互斥鎖,可以與std::unique_lock配合使用,把std::mutex放到unique_lock中時,mutex會自動上鎖,unique_lock析構時,同時把mutex解鎖。因此std::mutex可以保護同時被多個執行緒訪問的共享資料,並且它獨佔物件所有權,不支援對物件遞迴上鎖。

可以這樣理解:各個執行緒在對共享資源操作前都嘗試先加鎖,成功加鎖才能操作,操作結束解鎖。(下圖來自網路)

常用的成員函式有:

建構函式:std::mutex不支援copy和move操作,最初的mutex物件處於unlocked狀態。

lock函式:互斥鎖被鎖定。如果執行緒申請該互斥鎖,但未能獲得該互斥鎖,則申請呼叫的執行緒將阻塞(block)在該互斥鎖上;如果成功獲得該互訴鎖,則該執行緒一直擁有互斥鎖直到呼叫unlock解鎖;如果該互斥鎖已經被當前呼叫執行緒鎖住,則產生死鎖(deadlock)。

unlock函式:互斥鎖解鎖,釋放呼叫執行緒對該互斥鎖的所有權。

乙個簡單的例子:

std::mutex mtx;  // 建立乙個互斥鎖static void print_(int n, char c)
是c++標準程式庫中的乙個標頭檔案,定義了c++11標準中的一些用於併發程式設計時表示條件變數的類與方法等。

條件變數的引入是為了作為併發程式設計中的一種控制結構。當多個執行緒訪問同一共享資源時,不但需要用互斥鎖實現獨享訪問以避免併發錯誤(競爭危害),在獲得互斥鎖進入臨界區後還需要檢驗特定條件是否成立:

若不滿足該條件,擁有互斥鎖的執行緒應該釋放該互斥鎖,使用unique_lock函式把自身阻塞(block)並掛到條件變數的執行緒佇列中

若滿足該條件,擁有互斥鎖的執行緒在臨界區內訪問共享資源,在退出臨界區時通知(notify)在條件變數的執行緒佇列中處於阻塞狀態的執行緒,被通知的執行緒必須重新申請對該互斥鎖加鎖。

條件變數std::condition_variable用於多執行緒之間的通訊,它可以阻塞乙個或同時阻塞多個執行緒。std::condition_variable需要與std::unique_lock配合使用。

常用成員函式:

(1)建構函式:僅支援預設建構函式。

(2)wait():當前執行緒呼叫wait()後將被阻塞,直到另外某個執行緒呼叫notify_*喚醒當前執行緒。當執行緒被阻塞時,該函式會自動呼叫std::mutex的unlock()釋放鎖,使得其它被阻塞在鎖競爭上的執行緒得以繼續執行。一旦當前執行緒獲得通知(notify,通常是另外某個執行緒呼叫notify_*喚醒當前執行緒),wait()函式自動呼叫std::mutex的lock()。wait分為無條件被阻塞和帶條件的被阻塞兩種:

無條件被阻塞:呼叫該函式之前,當前執行緒應該已經對unique_locklck完成了加鎖。所有使用同乙個條件變數的執行緒必須在wait函式中使用同乙個unique_lock。該wait函式內部會自動呼叫lck.unlock()對互斥鎖解鎖,使得其他被阻塞在互斥鎖上的執行緒恢復執行。使用本函式被阻塞的當前執行緒在獲得通知(notified,通過別的執行緒呼叫 notify_*系列的函式)而被喚醒後,wait()函式恢復執行並自動呼叫lck.lock()對互斥鎖加鎖。

帶條件的被阻塞:wait函式設定了謂詞(predicate),只有當pred條件為false時呼叫該wait函式才會阻塞當前執行緒,並且在收到其它執行緒的通知後只有當pred為true時才會被解除阻塞。因此,等效於while (!pred()) wait(lck).

(3)notify_all: 喚醒所有的wait執行緒,如果當前沒有等待執行緒,則該函式什麼也不做。

(4)notify_one:喚醒某個wait執行緒,如果當前沒有等待執行緒,則該函式什麼也不做;如果同時存在多個等待執行緒,則喚醒某個執行緒是不確定的(unspecified)。

簡單的說就是,當std::condition_variable物件的某個wait函式被呼叫的時候,它使用std::unique_lock(通過std::mutex)來鎖住當前執行緒。當前執行緒會一直被阻塞,直到另外乙個執行緒在相同的std::condition_variable物件上呼叫了notification函式來喚醒當前執行緒。

是c++標準程式庫中的乙個標頭檔案,定義了c++11標準中一些表示執行緒、併發控制時進行原子操作的類與方法,主要宣告了兩大類原子物件:std::atomic和std::atomic_flag。

原子操作的主要特點是原子物件的併發訪問不存在資料競爭,利用原子物件可實現資料結構的無鎖設計。在多執行緒併發執行時,原子操作是執行緒不會被打斷的執行片段。

(1)atomic_flag類

是一種簡單的原子bool型別,只支援兩種操作:test_and_set(flag=true)和clear(flag=false)。

跟std::atomic的其它所有特化類不同,它是鎖無關的。

結合std::atomic_flag::test_and_set()和std::atomic_flag::clear(),std::atomic_flag物件可以當作乙個簡單的自旋鎖(spin lock)使用。

atomic_flag只有預設建構函式,禁用拷貝建構函式,移動建構函式實際上也禁用。

如果在初始化時沒有明確使用巨集atomic_flag_init初始化,那麼新建立的std::atomic_flag物件的狀態是未指定的(unspecified),既沒有被set也沒有被clear;如果使用該巨集初始化,該std::atomic_flag物件在建立時處於clear狀態。

(2)std::atomic類

std::atomic提供了針對bool型別、整形(integral)和指標型別的特化實現。每個std::atomic模板的例項化和完全特化定義乙個原子型別。

若乙個執行緒寫入原子物件,同時另乙個執行緒從它讀取,則行為良好定義。

原子物件的訪問可以按std::memory_order所指定建立執行緒間同步,並排序非原子的記憶體訪問。

std::atomic可以以任何可平凡複製(trivially copyable)的型別t例項化。

std::atomic既不可複製亦不可移動。

atomic_var_init(val):可以由建構函式直接執行此巨集初始化std::atomic物件。

std::atomic 常用的成員函式:

std::atomic::store(val) 函式將引數 val 複製給原子物件所封裝的值。

std::atomic::load() 讀取被原子物件封裝的值。

std::atomic::exchange(val) 讀取並修改被封裝的值,exchange 會將 val 指定的值替換掉之前該原子物件封裝的值,並返回之前該原子物件封裝的值,整個過程是原子的.

atomic() 預設建構函式,由預設建構函式建立的 std::atomic 物件處於未初始化(uninitialized)狀態,對處於未初始化(uninitialized)狀態 std::atomic物件可以由 atomic_init 函式進行初始化。

atomic (t val) 初始化建構函式,由型別 t初始化乙個 std::atomic物件。

atomic (const atomic&) 拷貝建構函式被禁用。

qt 多執行緒

qt通過三種形式提供了對執行緒的支援。它們分別是,一 平台無關的執行緒類,二 執行緒安全的事件投遞,三 跨執行緒的訊號 槽連線。這使得開發輕巧的多執行緒qt程式更為容易,並能充分利用多處理器機器的優勢。多執行緒程式設計也是乙個有用的模式,它用於解決執行較長時間的操作而不至於使用者介面失去響應。在qt...

Qt 多執行緒

qt 包含下面一些執行緒相關的類 qthread 提供了開始乙個新執行緒的方法 qthreadstorage 提供逐執行緒資料儲存 qmutex 提供相互排斥的鎖,或互斥量 qmutexlocker 是乙個便利類,它可以自動對 qmutex 加鎖與解鎖 qreadwriterlock 提供了乙個可以...

Qt多執行緒

今天學習qt的多執行緒,在學習多執行緒主要是兩個方面。一是多執行緒的基礎概念,二是多執行緒的同步,三是怎麼和主線程進行通訊。在這個主線程上面可以開始由qthread建立的物件的新的執行緒。這些由qthread建立的物件的新的執行緒之間的通訊,是通過使用含有互斥量,讀寫鎖,訊號量或者等待條件的共享變數...