1.1 程序
1.2 執行緒
1.3 執行緒與執行緒的區別聯絡
除了上面概念中所提到的,還有:
在乙個應用程式(程序)中同時執行多個小的部分(執行緒),這就是多執行緒。多個執行緒雖然共享一樣的資料,但是卻執行不同的任務。
併發是指在同乙個時間裡cpu同時執行兩條或多條命令。單核cpu和c++11以前實現的併發一般是偽併發。但隨著多核cpu的普及,c++11開始支援真正意義上的併發。
c++11可以通過多執行緒實現併發,這是一種比較底層、傳統的實現方式。c++11引入了5個頭檔案來支援多執行緒程式設計:////
是c++標準程式庫中的乙個標頭檔案,定義了c++11標準中一些互斥訪問的類與方法。#include // c++11 原子操作,限制併發程式對共享資料的使用,避免資料競爭
#include // 該標頭檔案主要宣告了std::thread類,另外std::this_thread命名空間也在該標頭檔案中
#include // c++11 互斥量mutex。在多執行緒環境中,有多個執行緒競爭同乙個公共資源,就很容易引發執行緒安全的問題
#include // 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函式:互斥鎖解鎖,釋放呼叫執行緒對該互斥鎖的所有權。
乙個簡單的例子:
是c++標準程式庫中的乙個標頭檔案,定義了c++11標準中的一些用於併發程式設計時表示條件變數的類與方法等。std::mutex mtx; // 建立乙個互斥鎖
static void print_(int n, char c)
條件變數的引入是為了作為併發程式設計中的一種控制結構。當多個執行緒訪問同一共享資源時,不但需要用互斥鎖實現獨享訪問以避免併發錯誤(競爭危害),在獲得互斥鎖進入臨界區後還需要檢驗特定條件是否成立:
若不滿足該條件,擁有互斥鎖的執行緒應該釋放該互斥鎖,使用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建立的物件的新的執行緒之間的通訊,是通過使用含有互斥量,讀寫鎖,訊號量或者等待條件的共享變數...