信息安全系统第十三周学习总结 20135218 姬梦馨
第十二章 并發編程
12.1 基于進程的并發編程
構造并發程序最簡單的方法——用進程
常用函數如下:
- fork
- exec
- waitpid
【基于進程的并發服務器】
- 使用SIGCHLD處理程序來回收僵死子進程的資源。
- 父進程必須關閉他們各自的connfd拷貝(已連接的描述符),避免存儲器泄露。
- 因為套接字的文件表表項中的引用計數,直到父子進程的connfd都關閉了,到客戶端的連接才會終止。
?
【基于I/O多路復用的并發編程】
使用select函數,要求內核掛起進程,只有在一個或多個I/O事件發生后,才將控制返回給應用程序。
int select(int n,fd_set *fdset,NULL,NULL,NULL);返回已經準備好的描述符的非0的個數,若出錯則為-1。
【基于I/O多路復用的并發事件驅動服務器】
狀態機:一組狀態、輸入事件、輸出事件和轉移。
自循環:同一輸入和輸出狀態之間的轉移。
?
I/O多路復用技術的優劣
相比基于進程的設計給了程序員更多的對進程行為的控制,運行在單一進程上下文中,每個邏輯流都能訪問全部的地址空間,在流之間共享數據很容易。
編碼復雜,隨著并發粒度的減小,復雜性還會上升。粒度:每個邏輯流每個時間片執行的指令數量。
?
?
12.3 基于線程的并發編程
Posix線程
Posix線程是C語言中處理線程的一個標準接口,允許程序創建、殺死和回收線程,與對等線程安全的共享數據。
線程的代碼和本地數據被封裝在一個線程例程中,
創建線程
線程通過調用pthread_create來創建其他線程。
int pthread_create(pthread_t *tid,pthread_attr_t *attr,func *f,void *arg);成功則返回0,出錯則為非零
當函數返回時,參數tid包含新創建的線程的ID,新線程可以通過調用pthread_self函數來獲得自己的線程ID。
pthread_t pthread_self(void);返回調用者的線程ID。
終止線程
當頂層的線程例程返回時,線程會隱式地終止。通過調用pthread_exit函數,線程會顯式地終止
void pthread_exit(void *thread_return);
回收已終止的線程資源
線程通過調用pthread_join函數等待其他線程終止。
int pthread_join(pthread_t tid,void **thread_return);成功則返回0,出錯則為非零
分離線程
在任何一個時間點上,線程是可結合或可分離的。一個可結合的線程能夠被其他線程收回其資源和殺死,在被回收之前,它的存儲器資源是沒有被釋放的。分離的線程則相反,資源在其終止時自動釋放。
int pthread_deacth(pthread_t tid);成功則返回0,出錯則為非零
初始化線程
pthread_once允許初始化與線程例程相關的狀態。
pthread_once_t once_control=PTHREAD_ONCE_INIT; int pthread_once(pthread_once_t *once_control,void (*init_routine)(void));總是返回0
12.4 多線程程序中的共享變量
?
【線程存儲器模型】
每個線程都有自己獨立的線程上下文,包括一個唯一的整數線程ID,棧、棧指針、程序計數器、通用目的寄存器和條件碼。
【將變量映射到存儲器】
- 全局變量:定義在函數之外的變量
- 本地自動變量:定義在函數內部但是沒有static屬性的變量。
- 本地靜態變量:定義在函數內部并有static屬性的變量。
【共享變量】
當且僅當變量的一個實例被一個以上的線程引用時,就說變量是共享的。
?
12.5用信號量同步線程
?
【進度圖】
將n個并發線程的執行模型化為一條n維笛卡爾空間中的軌跡線,將指令模型化為從一種狀態到另一種狀態的轉換。
轉換規則:
- 合法的轉換是向右或者向上,即某一個線程中的一條指令完成
- 兩條指令不能在同一時刻完成,即不允許出現對角線
- 程序不能反向運行,即不能出現向下或向左
?
?
【信號量】
- P(s):如果s是非零的,那么P將s減一,并且立即返回。如果s為零,那么就掛起這個線程,直到s變為非零。
- V(s):將s加一,如果有任何線程阻塞在P操作等待s變為非零,那么V操作會重啟線程中的一個,然后該線程將s減一,完成他的P操作。
?
?
12.6 使用線程來提高并行性
并行程序的加速比通常定義為:
其中,p為處理器核的數量,T為在p個核上的運行時間。
?
12.7 其他并發問題
【線程安全】
四個不相交的線程不安全函數類以及應對措施:
- 不保護共享變量的函數——用P和V這樣的同步操作保護共享變量
- 保持跨越多個調用的狀態的函數——重寫,不用任何static數據。
- 返回指向靜態變量的指針的函數——重寫;使用加鎖-拷貝技術。
- 調用線程不安全函數的函數——參考之前三種
【競爭】
當一個程序的正確性依賴于一個線程要在另一個線程到達y點之前到達他的控制流x點時,就會發生競爭。
為消除競爭,我么可以動態地為每個整數ID分配一個獨立的塊,并且傳遞給線程例程一個指向這個塊的指針。
【死鎖】
死鎖:一組線程被阻塞了,等待一個永遠也不會為真的條件。
- 程序員使用P和V操作順序不當,以至于兩個信號量的禁止區域重疊。
- 重疊的禁止區域引起了一組稱為死鎖區域的狀態。
- 死鎖是一個相當難的問題,因為它是不可預測的。
互斥鎖加鎖順序規則:如果對于程序中每對互斥鎖(s,t),給所有的鎖分配一個全序,每個線程按照這個順序來請求鎖,并且按照逆序來釋放,這個程序就是無死鎖的。
解決死鎖的方法
不讓死鎖發生:
- 靜態策略:設計合適的資源分配算法,不讓死鎖發生---死鎖預防;
- 動態策略:進程在申請資源時,系統審查是否會產生死鎖,若會產生死鎖則不分配---死鎖避免。
讓死鎖發生:
進程申請資源時不進行限制,系統定期或者不定期檢測是否有死鎖發生,當檢測到時解決死鎖----死鎖檢測與解除。
轉載于:https://www.cnblogs.com/ShadowStealer/p/5024750.html
創作挑戰賽新人創作獎勵來咯,堅持創作打卡瓜分現金大獎總結
以上是生活随笔為你收集整理的信息安全系统第十三周学习总结 20135218 姬梦馨的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: PLSQL 执行 for update
- 下一篇: 用之如锱铢弃之如敝履的意思