進程推進的合理有序同步——信號量
等待是進程同步的核心
信號量的出現(xiàn)是對于如果有多個P的時候,只有信號是不能喚醒所有生產(chǎn)者的,只能喚醒一個生產(chǎn)者。
- 信號只能喚醒一個生產(chǎn)者
信號量小于0對應(yīng)的是有多少個進程睡眠了
- 要學會等待(觀察信號量是否為負,如果是負數(shù)就需要等待)
停是很重要的
- 用臨界區(qū)來保護信號量
- 用信號量來支持進程的同步
信號量(整型變量)
互斥
讓進程之間的合作變得合理有序
實現(xiàn)這個的依據(jù)是信號量
想象一個司機和售票員的例子,司機要啟動車輛,這個時候應(yīng)該讓售票員先關(guān)門,然后發(fā)一個信號,然后司機可以啟動車輛,我們說司機是在等待一個信號。
同理,司機停車了,就需要發(fā)送一個信號給售票員,然后售票員才能開門。

等待就是阻塞,這個也是進程同步的核心。
比如說生產(chǎn)者--消費者模型,當緩沖區(qū)滿的時候,就要停下來,不然會溢出。如果緩沖區(qū)空了,就不敢再消費了,已經(jīng)沒有東西可以消費了。

引出信號量
之前的信號在程序里面的體現(xiàn)是counter,信號表示的只是有或無,它只能喚醒一個進程,然后就無效了,如果有n個進程,那么剩下的n - 1個進程就會一直sleep下去。所以我們需要一個量——信號量來表示有多少個進程在睡眠,喚醒的時候需要喚醒多少個進程。
信號量——記錄有多少個進程睡眠了
如果只有信號的話,只能是
發(fā)信號還有等信號,對應(yīng)的是喚醒和睡眠。

如果有了信號量的話,我們用
sem來表示,根據(jù)sem是多少來決定是喚醒還是睡眠,如果sem已經(jīng)小于0了,那就睡眠,然后消費者進程看到sem小于0了,就會去喚醒。這樣子就實現(xiàn)了
進程的走走停停


習題

P操作和V操作
- P操作對應(yīng)的是消費者
- V操作對應(yīng)的是生產(chǎn)者
睡眠和喚醒對應(yīng)的是都是信號量是否會小于0
P和V的2段代碼

生產(chǎn)者在共享緩沖區(qū)的時候,消費者不能進去
消費者在共享緩沖區(qū)的時候,生產(chǎn)者不能進去實現(xiàn)這一點是需要靠
互斥信號量來實現(xiàn)
為什么要保護信號量
因為多個進程會共同修改信號量,這樣會導致信號量的語義錯誤。這種錯誤就稱為——
和
調(diào)度有關(guān)的共享數(shù)據(jù)語義錯誤
什么是臨界區(qū)?
假如A進程有段代碼,B進程有段代碼,他們倆都有一個小部分的代碼涉及到了相同的信號量,那么這一小部分就是臨界區(qū),臨界區(qū)的執(zhí)行是一個原子操作——一個進程進去后修改完才能解鎖。
臨界區(qū)是成對or成組出現(xiàn)的
互斥——不能同時進入
死鎖預防就是2個方法
- 一次性申請所有資源
- 按序等待
死鎖避免
找到一個
安全序列(通過銀行家算法)
圖片.png
死鎖避免的代價太大了
因為每一個進程
Pi每次申請的時候,都要進行一次銀行家算法,看是否會引起死鎖,時間復雜度太高
圖片.png
圖片.png
死鎖檢測和恢復
發(fā)現(xiàn)問題,檢測到問題用的還是銀行家算法,不過執(zhí)行的次數(shù)少了一些了。
恢復的時候采用的是進程回滾,回滾到一定程度了看看是否還會死鎖。
但是選擇誰回滾,和實現(xiàn)回滾都比較麻煩。

死鎖忽略的方法


死鎖
多個進程由于
互相等待對方持有的資源,從而導致任何一個進程都無法執(zhí)行的情況。
死鎖的成因
- 互斥——一個資源被A進程占用后,其他進程無法使用
- A進程占有了資源后,不釋放,
還要去申請其他的資源
好比已經(jīng)占有了一條路,還要繼續(xù)前進到
其他的道路
- 環(huán)路等待——每個進程占有的資源和想要申請的資源形成了一個環(huán)路
相當于每輛公交車已經(jīng)有了自己的車道,還想要去占別人的車道,但是別人不讓,所以就
僵持住了。
死鎖的4個必要條件
- 互斥使用
- 不可搶占——資源只能進程自己放棄,比如
公交車自己開走
上面2點都是資源的固有屬性
- 請求和保持——進程已經(jīng)有了一個資源還不釋放,同時去申請其他的資源
-
循環(huán)等待
圖片.png



