多執行緒程式設計

2021-08-15 11:51:33 字數 3188 閱讀 5979

之前的部落格中有介紹過執行緒,但有些內容不夠完整,這篇文章是對執行緒的總結以及介紹執行緒安全問題。

linux執行緒基礎知識

執行緒的優點:

(1)建立乙個新執行緒的代價要比建立乙個新程序小的多

(2)與程序之間的切換相比,執行緒之間的切換需要作業系統所做的工作少的多

(3)執行緒占用資源要比程序少的多

(4)能充分利用多處理器的可並行數量

(5)在等待慢速i/o操作的同時,程式可執行其他操作

(6)計算密集型資料,為了能在多處理器機器上執行,將計算分解到多個執行緒中實現

(7)i/o密集型應用,為了提高效能,將i/o操作重疊。執行緒可以等待不同的i/o操作。

執行緒的缺點:

(1)效能缺失

乙個很少被外部事件阻塞的計算密集型執行緒往往無法同其他執行緒共享同乙個處理器。如果計算密集型執行緒的數量比處理器多,那麼可能會有較大的效能損失,這裡的效能損失指的是增加了額外的同步和排程開銷,而可用的資源不變。

(2)健壯性降低

編寫多執行緒需要更全面更深入的考慮,在乙個多執行緒程式裡,因時間分配上的細微偏差或者因共享了不該共享的變數而造成不良影響的可能性是很大的,即執行緒之間是缺乏保護的。

(3)缺乏訪問控制

程序是訪問控制的基本粒度,在乙個執行緒中呼叫某些os函式會對整個程序造成影響。

(4)程式設計難度提高

編寫與除錯乙個多執行緒程式比編寫乙個單執行緒程式難的多

void pthread_exit(void* value_ptr);
為什麼需要執行緒等待?

(1)已經退出的執行緒,其空間沒有被釋放,仍然在程序的位址空間內

(2)建立新的執行緒不會復用剛才退出的執行緒的位址空間

int pthread_join(pthread_t thread,void** value_ptr);
thread:執行緒id

value_pthr:指向乙個指標,後者指向執行緒的返回值。

呼叫該函式的執行緒將掛起等待,直到id為thread的執行緒終止。thread執行緒以不同的方法終止,通過pthread_join得到的終止狀態是不同的。

(1)如果thread通過return返回,value_ptr所指向的單元裡存放的是thread執行緒函式的返回值

(2)如果thread執行緒被別的執行緒呼叫pthread_cancel異常終止,value_ptr所指向的單元裡存放的是常數pthread_canceled

(3)如果thread執行緒是自己呼叫pthread_exit終止的,value_ptr所指向的單元裡存放的是pthread_exit的引數

(4)如果對thread執行緒的終止狀態不感興趣,則可以傳null給value_ptr引數。

互斥量

多執行緒程式設計中,多個執行緒之間需要共享一些全域性變數,這就可能造成程式執行結果和我們預期的不符,因為執行緒之間互相干擾。要保證程式的正確性,必須給臨界區加鎖。此時我們可以用到互斥量。

使用互斥量加鎖的流程如下:

初始化互斥量的兩種方法:

(1)靜態分配

pthread_mutex_t mutex =pthread_mutex_initalizer
(2)動態分配

int pthread_mutex_init(pthread_mutex_t* restrict mutex,const pthread_mutexattr_t *restrict attr);

//mutex:要初始化的互斥量

//attr:null

銷毀互斥量:

銷毀互斥量時需要注意:

(1)使用pthread_mutex_initializer初始化的互斥量不需要銷毀

(2)不要銷毀乙個已經加鎖的互斥量

(3)已經銷毀的互斥量,要確保後面不會有執行緒再嘗試加鎖

int pthread_mutex_dextroy(pthread_mutex_t* mutex);
呼叫pthread_lock時,可能會遇到以下情況:

(1)互斥量處於未鎖狀態,該函式將互斥量鎖定,同時成功返回

(2)發起函式呼叫時,其他執行緒已經鎖定互斥量,或者存在其他執行緒同時申請互斥量,但沒有競爭到互斥量,那麼pthread_lock呼叫會陷入阻塞,等待互斥量解鎖。

pthread_mutex_trylock:如果發現加了鎖,就非阻塞返回錯誤碼。

條件變數

當乙個執行緒互斥的訪問某個變數時,它可能發現在其他執行緒改變狀態之前,它什麼也做不了。

這種保證執行緒之間先後順序的機制就是條件變數。

有關條件變數的函式:

(1)初始化

int pthread_cond_init(pthread_cond_t* restrict cond,const pthread_condattr_t* restrict attr);

//cond:要初始化的條件變數

//attr:null

(2)銷毀

int pthread_cond_detroy(pthread_cond_t *cond);
(3)等待條件滿足

int pthread_cond_wait(pthread_cond_t *restrict cond,pthread_mutex_t *restrict mutex);

//cond:要在這個條件變數上等待

//mutex:互斥量

(4)喚醒等待

int pthread_cond_broadcast(pthread_cond_t* cond);

int pthread_cond_signal(pthread_cond_t* cond);

多執行緒程式設計的典型案例:

生產者消費者模型

讀者寫者模型

多執行緒程式設計

1 多執行緒的基本思路不是在介面執行緒執行費時的 而是專門啟動乙個執行緒 稱作工作執行緒 來完成,介面執行緒只負責介面的 顯示 和操作,而工作執行緒只負責耗時的操作過程。2 對於普通的win32應用程式來說,執行緒可以分為兩種 介面 ui user inte ce 執行緒和工作執行緒。介面執行緒一般...

多執行緒程式設計

如何編寫執行緒安全的dll 在我的工作中經常會編寫dll,這些dll有個共同的特點就是都有乙個初始化函式,乙個資源釋放函式,其他幾個函式都是核心功能函式。而且這些dll有時會被多個程序同時呼叫,這就牽扯到多程序的多執行緒呼叫dll的問題。有點繞口,以下我根據我實踐中遇到的問題,分四種情況分享一下我解...

多執行緒程式設計

1 執行緒的狀態 建立狀態 準備好了乙個多執行緒的物件 就緒狀態 呼叫了start 方法,等待cpu進行排程 執行狀態 執行run 方法 阻塞狀態 暫時停止執行,可能將資源交給其他執行緒使用 終止狀態 死亡狀態 執行緒銷毀 2 執行緒的常用方法 thread類 取得執行緒名稱 getname thr...