1. 程式人生 > >程序同步的三個經典問題

程序同步的三個經典問題

1. 有限快取問題 Bounded-Buffer Problem

要求:

  1. producer和consumer,二者不能對buffer進行操作
  2. 當buffer滿的時候,就不允許producer繼續寫
  3. 當buffer空的時候,就不允許consumer繼續讀

訊號量及其初始化

Semaphore mutex = 1; //buffer的鎖
Semapore full = 0; //滿位的數量
Semaphore empty = n; //空位的數量

producer簡單程式碼描述

/*PV形式*/
while(true){
	P(empty);
	P(mutex);
	//write...
	V(mutex);
	V(full);
}

/*wait signal形式*/
while(true){
	wait(empty);
	wait(mutex);
	//write...
	signal(mutex);
	signal(full);
}

consumer簡單程式碼描述

/*PV形式*/
while(true){
	P(full);
	P(mutex);
	//read...
	V(mutex);
	V(empty);
}

/*wait signal形式*/
while(true){
	wait(full);
	wait(mutex);
	//read...
	signal(mutex);
	signal(empty);
}

分析:
具有對稱性
先申請empty/full位,再申請緩衝區訪問許可權;先釋放mutex再釋放empty/full位

2. 讀者寫者問題 Readers and Writers Problem

要求:

  1. 多個讀者,只能read,不能write
  2. 多個寫者,既能read,也能write
  3. 允許多個reader同時讀
  4. 不允許reader和writer同時操作
  5. 不允許多個寫者同時操作

本質:保證一個writer程序必須與其他程序互斥地訪問共享物件

情況零:弱寫者優先(公平競爭)

要求:?
太簡單了(以後再補)

情況一:讀者優先

要求:

  1. 有讀者在讀,則其他讀者可讀,直到沒有讀者了,寫者才能寫
  2. 有寫者在寫,則其餘寫者和讀者等待

訊號量及其初始化

int readercount = 0;//共享變數,記錄當前讀者的數量
Semaphore mutex = 1;//readercount的鎖
Semaphore m = 1;//buffer的鎖

writer簡單程式碼描述

while(true){
	wait(m);

	//write

	signal(m);
}

reader簡單程式碼描述

while(true){
	wait(mutex);
	readercount++;
	if(readercount==1){
		wait(m);
	}
	signal(mutex);

	//read

	wait(mutex);
	readercount--;
	if(readercount==0){
		signal(m);
	}
	signal(mutex);
}

情況二:強寫者優先

要求:

  1. 寫者在寫,則其餘讀者和寫者等待;寫者寫完,優先釋放下一個寫者
  2. 讀者在讀,若無寫者等待,則其他讀者可讀
  3. 讀者在讀,若有寫者等待,則其他讀者等待

訊號量及其初始化

int readercount = 0;//共享變數,記錄當前讀者的數量
int writecount = 0;//共享變數,記錄當前寫者的數量

Semaphore mutex1 = 1;//readercount的鎖
Semaphore mutex2 = 1;//writecount的鎖

Semaphore read = 1;//buffer的讀鎖
semaphore write = 1;//buffer的寫鎖

Semaphore s = 1;//為了讓寫者優先

writer簡單程式碼實現

while(true){
	
	wait(mutex2);
	writecount++;
	if(writecount==1){
		wait(read);
	}
	signal(mutex2);

	wait(write);
	//write...
	signal(write);

	wait(mutex2);
	writecount--;
	if(writecount==0){
		signal(read);
	}
	signal(mutex2);

}

reader簡單程式碼實現

while(true){

	wait(s);
	wait(read);
	readercount++;
	if(readercount==1){
		wait(write);
	}
	signal(read);
	signal(s);

	//reading..

	wait(mutex1);
	readercount--;
	if(readcounter==0){
		signal(write);
	}
	signal(mutex1);

}

3.哲學家進餐問題 Dining-Philosophers Problem

要求:

  1. 有5個哲學家
  2. 哲學家只能吃飯或者思考,不能同時進行
  3. 哲學家只能拿兩根筷子才能吃飯

方案一:最多隻允許4個哲學家同時坐在桌子上

Semaphore chopstick[5]={1,1,1,1,1};//筷子是否可用
Semaphore seat=4;//可坐的位置

void philosppher(int i){
	
	while(true){
		
		think();
		
		wait(seat);//申請座位

		wait(chopstick[i]);
		wait(chopstick[(i+1)%5]);
		eat();
		signal(chopstick[(i+1)%5]);
		signal(chopstick[i]);

		signal(seat);

	}
}

方案二:非對稱方法,奇數哲學家拿左邊的筷子,偶數哲學家拿右邊的筷子

Semaphore chopstick[5]={1,1,1,1,1};//筷子是否可用

void philosppher(int i){

	while(true){
		think();

		if(i&1){
			wait(chopstick[i]);
			wait(chopstick[(i+1)%5]);
			eat();
			signal(chopstick[(i+1)%5]);
			signal(chopstick[i]);			
		}
		else{
			wait(chopstick[(i+1)%5]);
			wait(chopstick[i]);
			eat();
			signal(chopstick[i]);	
			signal(chopstick[(i+1)%5]);
		}
	}
}

方案三:只有當兩邊都有筷子的時候才會同時拿起兩隻筷子

藉助AND型訊號量,其基本思想是:將程序在整個執行過程中需要的所有資源一次性全部分配給程序,待程序使用完後再一起釋放。只要尚有一個資源未能分配給程序,其他所有可能為之分配的資源也不分配給它。

Semaphore chopstick[5]={1,1,1,1,1};//筷子是否可用

void philosppher(int i){

	while(true){
		
		think();

		Swait(chopstick[i],chopstick[(i+1)%5]);
		eat();
		Ssignal(chopstick[i],chopstick[(i+1)%5]);
	}
}