環境程式設計10

2021-10-09 10:38:27 字數 3350 閱讀 8781

一、基本概念

競爭與同步:

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

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

臨界區與臨界資源:

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

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

二、互斥量(互斥鎖)

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_tcond_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)。

UNIX環境高階程式設計之第10章 訊號

訊號是軟體中斷.很多比較重要的應用程式都需要處理訊號.訊號提供一種處理非同步時間的方法,例如,終端使用者鍵入中斷鍵,會通過訊號機制停止乙個程式,或及早終止管道中的下乙個程式.首先每個訊號都有乙個名字.這些名字都是以sig開頭.例如,sigabrt是夭折訊號,當程序呼叫abort函式是產生這種訊號.u...

網路程式設計10

accept 發生在三次握手之後。第一次握手 客戶端傳送 syn包 syn j 到伺服器。第二次握手 伺服器收到 syn包,必須確認客戶的 syn ack j 1 同時自己也傳送乙個 ask包 ask k 第三次握手 客戶端收到伺服器的 syn ack包,向伺服器傳送確認包 ack ack k 1 ...

程式設計技巧 10

1.旋轉最好用core animation void startanimation 2.怎麼製作優雅的tableview loading效果 可以在tableviewfooterview裡面設定這個效果,因為顯示出footerview的時候肯定在重新整理資料表之前 hytableviewfooter...