进程同步和信号量
進程的同步
進程合作:多進程完成同一個任務(wù)
?
實例1:
司機 ?????????????售票員
while)true){ ?????????while)true){
等待 啟動車輛; ??????????關(guān)門; 發(fā)送信號
?? 正常運行; ??????????售票;
?? 到站停車;發(fā)送信號 ??????等待 開門;
} ?????????????? }
兩個進程如何實現(xiàn)同步合作? 通過信號
實例2:文檔打印
問題:如果進程之間完全不知道對方的存在,會產(chǎn)生怎樣的錯誤?聯(lián)系實際
?
?
實際上的例子:生產(chǎn)者-消費者實例
共享數(shù)據(jù)
? 這些都是用戶態(tài)
?
生產(chǎn)者進程
while(true){
??while(counter == BUFFER_SIZE)
???? ; //阻塞 ?緩沖區(qū)滿,生產(chǎn)者停
??buffer[in] = item;
??in = (in+1)%BUFFER_SIZE;
??counter++; //發(fā)信號讓消費者走
}
?
消費者進程
while(true){
? while(counter == 0)
?? ; //阻塞 ?緩沖區(qū)空,消費者停
? item=buffer[out];
? out = (out-1)%BUFFER_SIZE;
? counter--; //發(fā)信號讓生產(chǎn)者走
}
?
等待是進程同步的核心
?
什么是進程同步?什么地方停,什么地方走?
進程同步?事實上就是讓進城走走停停,來保證多進程合作的合理有序
?
只發(fā)信號還不能解決全部問題
1.緩沖區(qū)滿以后生產(chǎn)者P1生產(chǎn)一個item放入,會sleep
2.有一個生產(chǎn)者P2生產(chǎn)一個item放入,會sleep
3.消費者C執(zhí)行1次循環(huán),counter == BUFFER_SIZE - 1, 發(fā)信號給P1, P1 wake up。
4.消費者C再執(zhí)行1次循環(huán),counter == BUFFER_SIZE - 2,P2不能被喚醒。
?
counter無法區(qū)分有多少生產(chǎn)者進程,不僅需要喚醒進程(發(fā)送信號),還需要一個量用來記錄睡眠進程的數(shù)量,來決定是否要發(fā)信號。
?
這就引出了信號量。
? ?
從信號到信號量
不只是等待信號,發(fā)信號? 對應(yīng)睡眠和喚醒
還能記錄一些信息
- 能記錄有2個進程等待就可以了 可以使用優(yōu)先隊列或者是棧來存儲
- 1.緩沖區(qū)滿,P1執(zhí)行,P1 sleep,記錄下一個進程等待?sem = -1
- 2.P2執(zhí)行,P2sleep,記錄下兩個進程等待 ??sem = -2
- 3.C執(zhí)行1次循環(huán),發(fā)現(xiàn)兩個進程等待,wakeup一個 wakeup P1?sem=-1
- C再執(zhí)行1次循環(huán),發(fā)現(xiàn)一個進程等待,wakeup一個 wakeup P2?sem=0
- C再執(zhí)行1次循環(huán)4,發(fā)現(xiàn)沒有進程等待,sem = 1
- P3執(zhí)行
總結(jié):
什么時候減一?
當(dāng)有一個進程sleep,信號量-1
什么時候加一?
當(dāng)發(fā)現(xiàn)信號量是負的,信號量+1,并且發(fā)信號wakeup; 如果發(fā)現(xiàn)信號量是正的,那么不發(fā)信號,累加信號量。
?
問題:一種資源的數(shù)量是8,這個資源對應(yīng)的信號量的當(dāng)前值是2,說明():
資源的數(shù)量是8,說明初始的sem是8,當(dāng)前的信號量變?yōu)?,說明沒有進程在等待等待這個資源。
?
什么是信號量?信號量的定義
信號量:1965年,由荷蘭學(xué)者Dijkstra提出的一種特殊變量,量用來記錄,信號用來sleep和wakeup
?
struct semaphore
{
?? int value; //記錄資料個數(shù)
?? PCB *queue; //記錄等待在該信號量上的進程
}
P(semaphore s); //消費資源
V(semphore s); //產(chǎn)生資源
?
P(semphore s)
{
?? s.value--;
?? if(s.value < 0){
???? sleep(s.queue);?
?? }
}
?
問:V(s)的代碼?
V(semphore s){
??s.value++;
? if(s.value <= 0){
?? wakeup(s.queue);
? }
}
?
Producer(item){
?? P(empty);
?? P(mutex);
?? 讀入in;將item寫入到in的位置上;
?? V(mutex);
?? V(full);
}
?
Constumer() {
?? P(full);
?? P(mutex);
?? 讀入out;從文件out位置讀出到item;打印item;
?? V(mutex);
?? V(empty);
}
?
用信號量解決生產(chǎn)者-消費者問題
int fd = open("buffer.txt");
write(fd, 0, sizeof(int)); //寫in
write(fd, 0, sizeof(int)); //寫out
?
semaphore full = 0;
semaphore empty = BUFFER_SIZE;
semaphore mutex = 1;
?
如何理解用信號量的生產(chǎn)者消費者代碼?
full用來判斷是否為空,empty用來判斷是否為滿。通過P和V來睡眠和喚醒進程,并釋放信號量。
?
如何實現(xiàn)互斥訪問?
當(dāng)進入緩沖區(qū)時,將mutex的值變?yōu)?,用完之后在釋放。
?
?
轉(zhuǎn)載于:https://www.cnblogs.com/ACFLOOD/p/5451409.html
總結(jié)
- 上一篇: 使用mybatis-generator自
- 下一篇: 虚拟机检测手段