目录
司机与售票员(同步问题)
生产者-消费者问题
问题1:
问题2:
读者--写者问题
过桥问题:
哲学家进餐问题
司机与售票员(同步问题)
semphore close,stop;//设置信号量:关车门,停车
close.value=0,stop.value=0;//其值初始化为0
driver:P1(){
while(1){
wait(close);//司机等待关门信号
启动;
正常运行;
到站停车;
signal(stop);//向售票员发出停车信号
}
}
conductor:P2(){
while(1){
关车门;
signal(close);//向司机发送关车门信号
售票;
wait(stop);//等待停车信号
开车门;
}
}
生产者-消费者问题
其中,生产者和消费者之间既有同步的合作关系,又有互斥(两者不能同时访问临界资源缓冲区)的关系。假设缓冲池里有n个缓冲区。
semaphore empty,full,mutex;
empty.value=n,full.value=0,mutex.value=1;
producer():
{
while(1):{
生产一个产品;
wait(empty);
wait(mutex);
放入缓冲取;
signal(mutex);
signal(full);
}
}
consumer():{
while(1){
wait(full);
wait(mutex);
从缓冲区取一个产品;
signal(mutex);
signal(empty);
使用产品;
}
}
问题1:
在基础的生产者消费者问题的基础上,要求,在一个消费者取完10件产品后下一个消费者才能继续取时。对消费者的代码做如下改动:
for循环是保证取10件产品,信号量_mutex是保证一个消费者还未取10件时,其他消费者不能取。
semaphore _mutex=1;
wait(_mutex);
for(int i=1;i<=10;i++){
consumer();
}
signal(_mutex);
问题2:
车间一生产A产品,放在货架F1上;车间二生产B产品,放在货架F2上;F1,F2各有10个位置,车间C:用A产品和B产品装配成最终的产品。用P、V操作表示。
semaphore f1_mutex,f2_mutex,A_full,A_empty,B_full,B_empty;
f1_mutex.value=1,f2_mutex.value=1;
A_full.value=0,A_empty.value=10;
B_full.value=0,B_empty.value=10;
PA():{
while(1){
生产A;
wait(A_empty);
wait(f1_mutex);
将A放在货架F1上;
signal(f1_mutex);
signal(A_full);
}
}
PB():{
while(1){
生产B;
wait(B_empty);
wait(f2_mutex);
将B放在货架F2上;
signal(f2_mutex);
signal(B_full);
}
}
PC():{
while(1){
wait(A_full);
wait(f1_mutex);
从F1取A;
signal(f1_mutex);
signal(A_empty);
wait(B_full);
wait(f2_mutex);
从F2取B;
signal(f1_mutex);
signal(B_full);
}
}
总结 这类题的分析步骤:
① 分析题目中有几个进程,确定进程间的关系,画出有向边;
② 原代码不变照抄,确定信号量;
③ 分析同步/互斥关系;
④ 有向边指向谁,谁前wait
⑤ 有向边从谁出发,谁后signal
⑥ 最后分析信号量的初始值(得保证能运行,无死锁)
读者--写者问题
要求: 1. 可以同时读;
2. 读写不能同时进行
3.不能同时写
semaphore rmutex, wmutex;
rmutex.value=1,wmutex.value=1;
int readcount=0;
Read():{
while(1){
wait(rmutex);
if(readcount==0) wait(wmutex);
readcount++;
signal(rmutex);
...
开始执行读;
...
wait(rmutex);
readcount--;
if(readcount==0) signal(wmutex);
signal(rmutex);
}
}
Write():{
while(1){
wait(wmutex);
执行写;
signal(wmutex);
}
}
过桥问题:
要求:同一个方向的能同时过去,不同方向的,不能同时过。
semaphore brigde, leftMutex, rightMutex;
bridge.value=1, leftMutex.value=1, rightMutex.value=1;
int leftCount = 0, rightCount = 0 ;
P_left():{
while(1){
wait(leftMutex);
if(leftCount==0) wait(bridge);
leftCount++;
signal(leftMutex);
从左边过桥;
wait(leftMutex);
leftCount--;
if(leftCount==0)
signal(bridge);
signal(leftMutex);
}
}
P_right():{
while(1){
wait(rightMutex);
if(rightCount==0) wait(bridge);
rightCount++;
signal(rightMutex);
从右边过桥;
wait(rightMutex);
rightCount--;
if(rightCount==0)
signal(bridge);
signal(rightMutex);
}
}
另一种写法,以Right为例
P_right():{
while(1){
wait(rightMutex);
rightCount++;
if(rightCount==1)//第从左向右的一个人上桥
wait(bridge);
signal(rightMutex);
从左向右过桥;
wait(rightMutex);
rightCount--;
if(rightCount==0)
signal(bridge);//向右的人都走下桥了
signal(rightMutex);
}
}
哲学家进餐问题
原问题,5个哲学家,5根筷子,一个盘子,为了更公平的实现并且保证不会有死锁的P、V操作
设筷子编号0,1,2,3,4,5; 哲学家编号:1,2,3,4,5
semaphore chopstick[5]={1,1,1,1,1};
while(1){
思考;
if(i%2==0){ //编号为偶数的哲学家先拿其右边筷子
wait(chopstick[i%5]);
wait(chopstick[i-1])
用筷子吃饭;
signal(chopstick[i%5]);
signal(chopstick[i-1]);
}else{ //编号为奇数的哲学家先拿左边的筷子,这样防止多个哲学家并发执行时发生死锁
wait(chopstick[i-1]);
wait(chopstick[i%5])
用筷子吃饭;
signal(chopstick[i-1]);
signal(chopstick[i%5]);
}
}
如果将原问题中的一个盘子变成现在有m个碗,n个哲学家,为保证更多哲学家一起用餐的PV操作
semaphore chopstick[n]={1,1,1,...,1},bowl=min{n-1,m};//初始值的设定是难点
while(1){
思考;
wait(bowl);
wait(chopstick[i%5]);
wait(chopstick[i-1])
用筷子吃饭;
signal(chopstick[i%5]);
signal(chopstick[i-1]);
signal(bowl);
}
注:wait(bowl)必须写在最前面,防止死锁!



