執行緒通訊,鎖

2021-10-24 08:01:36 字數 3437 閱讀 9733

一、基本概念

競爭與同步:

同乙個程序中的執行緒能共享程序中的絕大多數資源,當它們隨意競爭時可以導致資源會破壞、髒資料、不完整、不一致等問題。

通過一些方法讓程序在競爭資源時相互協調,避免出現資料不完全、不一致等問題,這就叫執行緒同步。

臨界區與臨界資源:

被多個執行緒同時訪問的**叫臨界區,被同時訪問的資源叫臨界資源。

原子操作:中間不會打斷的操作叫原子操作。

二、互斥量(互斥鎖)

pthread_mutex_t 是一種資料型別,可以定義變數。

int pthread_mutex_init(pthread_mutex_t  *mutex,  const  pthread_mutexattr_t *mutexattr);

功能:初始化互斥量,也可以使用pthread_mutex_initializer初始化,預設處於開鎖狀態。

int pthread_mutex_lock(pthread_mutex_t *mutex);

功能:對互斥量加鎖,成功則繼續執行,失敗則阻塞,直到互斥量解鎖,才返回。

int pthread_mutex_trylock(pthread_mutex_t *mutex);

功能:嘗試對互斥量加鎖,成功(0)或失敗(ebusy)都立即返回。

int pthread_mutex_unlock(pthread_mutex_t *mutex);

功能:對互斥量解鎖

int pthread_mutex_destroy(pthread_mutex_t *mutex);

功能:銷毀互斥量

三、訊號量

與xsi中的訊號量原理相同,執行緒之間所使用的計數器,用於控制訪問有限的共享資源的執行緒數。

int sem_init(sem_t *sem, int pshared, unsigned int value);

功能:初始化訊號量

sem:被初始化的訊號量

pshared:

0 只能在程序內使用

非0 表示該訊號量可以用共享記憶體的方式,多個程序共享(linux不支援)。

value:訊號量的初始值

int sem_wait(sem_t *sem);

功能:對號量減1,如果不夠減則阻塞

int sem_trywait(sem_t *sem);

功能:對訊號量減1,成功(0)或失敗(eagain)都立即返回

int sem_timedwait(sem_t *sem, const struct timespec *abs_timeout);

功能:對訊號量減,如果不夠減則等待abs_timeout時間,超時後返回(etimedout)。

int sem_post(sem_t *sem);

功能:對訊號量加1。

int sem_destroy(sem_t *sem);

功能:銷毀訊號量

四:死鎖

1、什麼是死鎖

多個程序或執行緒互相等待對方的資源,在得到新的資源之前不會釋放自己的資源,這樣就形成了迴圈等待,這種現象被稱為死鎖。

2、產生死鎖的四大必要條件

資源互斥:資源只有兩種狀態,只有可用和不可用兩狀態,不能同時使用,同一時刻只能被乙個程序或執行緒使用。

占有且請求:已經得到資源的程序或執行緒,繼續請求新的資源,並持續占有舊的資源。

資源不可剝奪:資源已經分配程序或執行緒後,不能被其它程序或執行緒強制性獲取,除非資源的佔有者主動釋放。

環路等待:死鎖發生時,系統中必定有兩個或兩個以上的程序或執行緒組成一條等待環路。

注意:死鎖一旦產生基本無解,現在的作業系統無法解決死鎖,因此只能防止死鎖產生。

3、防止死鎖產生的方法

破壞互斥條件:相辦法讓資源能夠共享使用。

缺點:受環境或資金的影響無法讓資源共享。

破壞占用且請求條件:採用預先靜態分配的方法,程序或執行緒在執行前一次申請所有資源,在資源沒有滿足前不投入執行。

缺點:系統資源會被嚴重浪費,因為有些資源可能開始時使用,而有些資源結束時才使用。

破壞不可剝奪條件:當乙個程序或執行緒已經占有乙個不可剝奪的資源時,請求新資源時無法滿足,則釋放已經占有的資源,一段時間後再重新申請。

缺點:該策略實現起來比較複雜,釋放已經獲取資源可能會導致前一階段的工作失效,反覆的申請釋放資源會增加系統開銷,占用cpu和暫存器、記憶體等資源。

破壞迴圈等待條件:給每個資源進行編號,程序或執行緒按照順序請求資源,只有拿到前一外資源,才能繼續請求下乙個資源。

缺點:資源的編號必須相對穩定,資源新增或銷毀時會受到影響。

演算法:銀行家演算法

4、如何判斷死鎖

1、畫出資源分配圖

2、簡化資源分配圖

3、使用死鎖定理判斷:如果沒有環路肯定不會出現死鎖。

五、條件變數

當某些條件滿足時可以讓執行緒自己可以進入睡眠,也可以在某些條件滿足時可以被其它執行緒喚醒。

int pthread_cond_init(pthread_cond_t *cond,    pthread_condattr_t*cond_attr);

功能:初始化條件變數,也可以使用pthread_cond_initializer。

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

功能:讓當前執行緒睡入cond中,並解鎖mutex。

int pthread_cond_signal(pthread_cond_t *cond);

功能:喚醒cond中的乙個執行緒,之前的鎖必須處於開啟狀態,執行緒醒來後會自動把鎖再加上。

int pthread_cond_broadcast(pthread_cond_t *cond);

功能:喚醒cond中的所有執行緒,執行緒醒來時互斥量必須能再次加鎖。

int pthread_cond_timedwait(pthread_cond_t *cond, pthread_mutex_t *mutex, const struct timespec *abstime);

功能:讓當前執行緒睡入cond,只睡abstime時間,超時後會自動醒來。

int pthread_cond_destroy(pthread_cond_t *cond);

功能:銷毀條件變數

注意:使用條件變數可以實現生產者與消費者模型。

六、生產者與消費者模型

生產者:產生資料的執行緒

消費者:使用資料的執行緒

倉庫:臨時儲存資料的緩衝區

可能產生的問題:

生產快於消費,倉庫爆滿,撐死。

消費快於生產,倉庫空虛,餓死。

利用條件變數解決問題:

當緩衝區滿的時候,生產線程睡入條件變數(full),通知消費執行緒全部醒來(null)。

當緩衝區空的時候,消費執行緒睡入條件變數(null),通訊生產線程全部醒來(full)。

執行緒間通訊《互斥鎖,讀寫鎖》

1 互斥鎖 為了保護共享資源,使我們執行緒可以單獨使用這個共享資源,使用之前先上鎖,那其他程序要使用的時候,就需要等待到這個執行緒用完之後,需要開鎖。互斥鎖的使用 幫助文件預設沒有安裝,我們需要手動安裝 sudo apt get install manpages posix dev 宣告這個互斥鎖 ...

執行緒狀態 互斥鎖 通訊

標籤 空格分隔 多執行緒 void touchesbegan nsset touches withevent uievent event void run 注意點互斥鎖和自旋鎖不同點 盡量避免多執行緒搶奪同一塊資源,盡量將加鎖 資源搶奪的業務邏輯交給伺服器端處理,減小移動客戶端的壓力 void pe...

05執行緒通訊 互斥鎖

1.建立乙個互斥鎖 int pthread mutex init ptread mutex t mutex,const pthread mutexattr t attr 成功返回0 失敗eof 2.申請乙個互斥鎖 int pthread mutex lock ptread mutex t mutex...