進程間的交互分爲競爭關係、協作關係。
1、競爭關係
由於計算機內資源有限,或者說某幾個進程必須共享某些資源與變量,這時候就不可避免的會出現競爭,進程的相互競爭就會穿死鎖和飢餓問題,飢餓問題已解釋。
死鎖問題是指一組進程如果都獲得了部分資源,還想要得到其他進程佔用的資源,最終所有進程都將陷入死鎖,即都在等待,每個進程都不會先放手自己佔有的資源。
進程互斥:若干進程在使用共享資源的時候,其他進程必須等待正在使用的進程釋放該進程,臨界區管理是解決進程互斥問題的辦法。
2、協作關係
某些任務需要很多進程爲其分工來完成,這時候需要協調互相之間的關係,比如某個進程在進行到某個點之後需要等待某些進程的消息和信號才能繼續執行。(進程同步。
臨界區:併發進程中與共享變量有關的程序段叫“臨界區”。
臨界資源:共享變量代表的資源叫做“臨界資源”。
臨界區調度原則:空閒讓進、忙則等待、有限等待、讓權等待。
3、信號量解決
p表示獲取資源,一般會跟value--,v表示釋放資源,後接value++。p、v一定是成對出現在同一個進程之中,否則會出現資源泄漏。
經典問題:哲學家進餐問題、生產者消費者問題、讀寫者問題、理髮師問題。
哲學家進餐問題:五個哲學家圍坐一張圓桌,桌上僅有五根筷子,每位哲學家只能拿起與他相鄰的兩根筷子吃飯。五根筷子都是臨界資源
設爲:semaphore fork[5] = {1,1,1,1,1};
philosopher_i()
while(true){
{think()};
p(fork[i]);
p(fork[(i+1)%5]);
{eat()};
v(fork[i]);
v(fork[(i+1)%5]);
}
此法會造成死鎖問題,比如五個哲學家進程同時啓動,則在申請第二個筷子的時候,所有進程都會等待別的進程釋放手中的資源,這就是死鎖。破解:1可以設置條件,只有當左右兩邊的筷子都空閒的時候,才允許去拿筷子(AND信號量機制);2只允許最多四個人同時去拿筷子,這樣總有一個人能拿到兩個完成進程,最後釋放資源;
生產者消費者問題:顧名思義,生產的同時有消費。
設置緩衝區buf[n],以便協調生產與消費的速度,但對緩衝區的訪問必須是互斥的,否則還沒生產即被消費。
設置互斥信號量爲mutex初始化爲1,empty表示buf內空餘區數,初始化爲n,full相反,初始化爲0,。
process producer()
while(true)
{
produce an item in nextp;
p(empty);//empy--
p(mutex);mutex = 1
buf[in] = nextp;
in = (in+1)%k;//round buffer
counter++;
v(mutex);//mutex = 0
v(full);//full++
}
process consumer()
while(true)
{
p(full);
p(mutex);
nextc = buf[out];
out = (out+1)%k;
counter--;
v(mutex);
v(empty);
consume item nextp
}
讀寫者問題:多個進程共享一個數據區,讀進程只讀,寫進程只寫。如售票系統的查詢與更新,如果沒有比較好的控制會出現同時售出同一張票這種情況。
可以設置mutex爲讀者之間的互斥訪問,wrt爲寫者之間以及寫者與讀者之間的互斥訪問。
當沒有寫者進程,多讀者進程可以併發,當有讀者進程的時候,寫者進程阻塞。稱爲讀者優先。
process reader()
while(true){
p(mutex);
readercount++;
if(readercount>=1) p(wrt);
v(mutex);
reading data;
p(mutex);
readercount--;
if(readercount==0) v(wrt);
v(mutex);
}
process writer()
while(true){
p(wrt);
writing data;
v(wrt);
}
寫者優先:上述讀者優先實際上也不是優先讀者,只是相對寫者優先來說的概念。
寫者優先需要設置wrt控制寫者之間的衝突、readcount計數讀者,writecount計數寫者,讀者之間的互斥rmutex,讀寫者之間的互斥rwmutex(控制由寫者優先);
process reader()
while(true){
p(rwmutex);
p(rmutex);
readcount++;
if(readcount == 1) p(wdr);//有讀進程,控制不可以寫
v(rmutex);
v(rwmutex);
read data..........
p(rmutex);
readcount--;
if(readcount==0) v(wdr);
v(rmutex);
}
process writer()
while(true){
p(wmutex);
writercount++;
if(writercount==1) p(rwmutex);
v(wmutex);
p(wrt);
{writing......}
v(wrt);
p(wmutex);
writercount--;
if(writercount==0) v(rwmutex);
v(wmutex);
}