操作系统---进程同步问题(信号量机制)

目录

司机与售票员(同步问题)

生产者-消费者问题

问题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)必须写在最前面,防止死锁!

  • 2
    点赞
  • 28
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值