進程的同步spa
進程合做:多進程完成同一個任務 3d
實例1:blog
司機 售票員 隊列
while)true){ while)true){ 進程
等待 啓動車輛; 關門; 發送信號 資源
正常運行; 售票; 文檔
到站停車;發送信號 等待 開門; 同步
} } it
兩個進程如何實現同步合做? 經過信號 多進程
實例2:文檔打印
問題:若是進程之間徹底不知道對方的存在,會產生怎樣的錯誤?聯繫實際
實際上的例子:生產者-消費者實例
共享數據
這些都是用戶態
生產者進程
while(true){
while(counter == BUFFER_SIZE)
; //阻塞 緩衝區滿,生產者停
buffer[in] = item;
in = (in+1)%BUFFER_SIZE;
counter++; //發信號讓消費者走
}
消費者進程
while(true){
while(counter == 0)
; //阻塞 緩衝區空,消費者停
item=buffer[out];
out = (out-1)%BUFFER_SIZE;
counter--; //發信號讓生產者走
}
等待是進程同步的核心
什麼是進程同步?什麼地方停,什麼地方走?
進程同步 事實上就是讓進城走走停停,來保證多進程合做的合理有序
只發信號還不能解決所有問題
1.緩衝區滿之後生產者P1生產一個item放入,會sleep
2.有一個生產者P2生產一個item放入,會sleep
3.消費者C執行1次循環,counter == BUFFER_SIZE - 1, 發信號給P1, P1 wake up。
4.消費者C再執行1次循環,counter == BUFFER_SIZE - 2,P2不能被喚醒。
counter沒法區分有多少生產者進程,不只須要喚醒進程(發送信號),還須要一個量用來記錄睡眠進程的數量,來決定是否要發信號。
這就引出了信號量。
從信號到信號量
不僅是等待信號,發信號? 對應睡眠和喚醒
還能記錄一些信息
總結:
何時減一?
當有一個進程sleep,信號量-1
何時加一?
當發現信號量是負的,信號量+1,而且發信號wakeup; 若是發現信號量是正的,那麼不發信號,累加信號量。
問題:一種資源的數量是8,這個資源對應的信號量的當前值是2,說明():
資源的數量是8,說明初始的sem是8,當前的信號量變爲2,說明沒有進程在等待等待這個資源。
什麼是信號量?信號量的定義
信號量:1965年,由荷蘭學者Dijkstra提出的一種特殊變量,量用來記錄,信號用來sleep和wakeup
struct semaphore
{
int value; //記錄資料個數
PCB *queue; //記錄等待在該信號量上的進程
}
P(semaphore s); //消費資源
V(semphore s); //產生資源
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);
}
用信號量解決生產者-消費者問題
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;
如何理解用信號量的生產者消費者代碼?
full用來判斷是否爲空,empty用來判斷是否爲滿。經過P和V來睡眠和喚醒進程,並釋放信號量。
如何實現互斥訪問?
當進入緩衝區時,將mutex的值變爲0,用完以後在釋放。