几个进程同步问题

1.消费者-生产者

semaphore empty = n;	// 空闲缓冲区数量
semaphore full = 0;		// 产品数量
semaphore mutex = 1;	// 对缓冲区的互斥操作

void producer(){
    do{
        生产一个产品;
        wait(empty);
        wait(mutex);	// 实现互斥的P操作一定要在实现同步的P操作之后
        把产品放入缓冲区;
        signal(mutex);
        siganl(full);
    }while(true);
}

void consumer(){
    do{
        wait(full);
        wait(mutex);
        从缓冲区取出一个产品;
        signal(mutex);
        siganl(empty);
        消费一个产品;
    }while(true);    
}

2.多生产者-消费者

问题描述

桌上有一个只能放入一个水果的盘子,爸爸专向盘子中放苹果(apple),妈妈专向盘子中放橘子(orange),儿子专等吃盘子中的橘子,女儿专等吃盘子里的苹果 。

问题分析

多生产者是指多个类型的生产者和多个类型的消费者生产多种产品,盘子即为缓冲区,盘子只能放一个水果,缓冲区大小为1

代码

semaphore mutex = 1;	// 用于对缓冲区的互斥操作
semaphore apple = 0;
semaphore orange = 0;
/*semaphore empty = 0;semaphore full = 0;*/
semaphore plate	= 1;	// 盘子中还可以放多少个水果	
void father(){
   	准备一个苹果;
    wait(plate);
    wait(mutex);
    把苹果放进盘子;
    siganl(mutex);
    siganl(apple);
}

void mother(){
    准备一个橘子;
    wait(plate);
    wait(mutex);
    把橘子放进盘子;
    siganl(mutex);
    siganl(orange);   
}

void son(){
    wait(orange);
    wait(mutex);
    从盘子中取出橘子;
    siganl(mutex);
    siganl(plate);
    吃橘子;
}

void daughter(){
    wait(apple);
    wait(mutex);
    从盘子中取出橘子;
    siganl(mutex);
    siganl(plate);
    吃苹果;
}

3.读者写者问题

之前已经有一篇博客,详细的阐述过这个问题,包括读者优先,写者优先,读写公平。有兴趣可以移步读者写者问题(超级详细的分析读者优先,读写平等,写者优先)

4.嗜睡的理发师问题

问题描述

一个理发店由一个有N张沙发的等候室和一个放有一张理发椅的理发室组成;
没有顾客要理发时,理发师便去睡觉
当一个顾客走进理发店时
如果所有的沙发都已被占用,他便离开理发店;
否则,如果理发师正在为其他顾客理发,则该顾客就找一张空沙发坐下等待;
如果理发师因无顾客正在睡觉,则由新到的顾客唤醒理发师为其理发。
理发完成后,顾客必须付费,直到理发师收费后才能离开理发店

代码

int count=0;       		//对理发店中的顾客进行计数
semaphore mutex=1;  	//实现顾客进程对count变量的互斥访问
semaphore sofa=N;   	//对应于等候室中N张沙发
semaphore empty=1;  	//表示是否有空闲的理发椅
semaphore full=0;   	//表示理发椅上是否有等待理发的顾客
semaphore payment=0;	//用来等待付费
semaphore receipt=0;	//用来等待收费

void guest() {   
    do{
		wait(mutex);
        if  (count>N) {
            signal(mutex); //如果所有的沙发都已被占用,他便离开理发店
   			离开理发店;
		}
        else {
            count ++ 
            signal(mutex);
            if (count>1)  {
               //如果理发师正在为其他顾客理发,则该顾客就找一张空沙发坐下等待  
               wait(sofa);
               在沙发中就座;
               wait(empty);
               从沙发上起来;
               signal(sofa);
            }
           
            else {   /*count=1*/
               wait(empty);  //在理发椅上就座;
            }
            //顾客接受理发,结束后付费离开
            signal(full);
            理发;
            付费;
            signal(payment)wait(receipt);
            从理发椅上起来;
            signal(empty);
            wait(mutex);
            count --;
            signal(mutex);
            离开理发店;
    }while(true);
}

void barber() {
    do {
		wait(full);
        给顾客理发;
        siganl(payment);
        收费;
        wait(receipt);
    } while(true);
}

5.哲学家就餐问题

问题描述

五位哲学家围桌而坐
桌上有5个碗和5只筷子
哲学家在思考问题时不需要任何资源,思考完问题后进入进餐态。
每人必须获得左右两支筷子才能进餐

代码

//最简单的用AND信号量机制
/*仅当哲学家的左、右两根筷子均可用时,才允许他拿起筷子进餐*/
semaphore chopsticks[5] = {1,1,1,1,1};
void philosopher(){
    do{
        think;
        Swait(chopsticks[i],chopsticks[(i+1)%5]);//一次申请左边右边的筷子,有一个筷子申请不到,就阻塞
        eat;
        Ssignal(chopsticks[i],chopsticks[(i+1)%5]);
    }while(true);

}

//这种方法用了两种两份代码实现,下面这一份是我写的
/*至多只允许有四位哲学家同时去拿左边的筷子,最终能保证至少有一位哲学家能够进餐,并在用毕时能释放出他用过的两根筷子,从而使更多的哲学家能够进餐。*/
semaphore chopsticks[5] = {1,1,1,1,1};
semaphore count = 0; //拿起左边筷子的哲学家的人数
semaphore mutex = 1; //互斥访问count
void philosoher(){
    do{
        think;
        wait(mutex);
        if(count<=4){	
            count++;
            wait(chopsticks[i]);
            wait(chopsticks[(i+1)%5]);
            signal(mutex);
            eat;		// 吃完就释放筷子
            signal(chopsticks[i]);
            signal(chopsticks[(i+1)%5]);
            wait(mutex);
            count--;	
            signal(mutex);
        }
        else{	//已经有4个人拿了左边的筷子了,第五个哲学家不应该拿剩下一根筷子,什么也不做
            siganl(mutex);
        }
    }while(true);
}

//老师给的答案
semaphore chopstick[5]={1,1,1,1,1}, Sm=4;
void P(int i) {
  do {
    wait(Sm);
    wait(chopstick[i]);
    wait(chopstick[i+1] mod 5);
    eat;
    signal(chopstick[i]);
    signal(chopstick[i+1] mod 5);
    signal(Sm);
    think;
  } while[TRUE];
}
void main(){
  cobegin
    for (int i=1; i<=5; i++){
      P(i);
    }
  coend
}
/*方法二:防止死锁的策略为:规定奇数号哲学家先拿他左边的筷子,然后再去拿右边的筷子;而偶数号哲学家则相反。按此规定,将是1、 2号哲学家竞争1号筷子;3、4号哲学家竞争3号筷子。即五位哲学家都先竞争奇数号筷子,获得后,再去竞争偶数号筷子,最后总会有一位哲学家能获得两只筷子而进餐。
为每只筷子设置一个初值为1的信号量chopstick[i](i=0, …, 4),第i个哲学家的活动可描述为:*/
semaphore chopstick[5]={1,1,1,1,1};
void P(int i) {
  do {
    if (i mod 2 == 1) { //奇数号哲学家
      wait(chopstick[i]);	//先拿左边的,左右不重要,哲学家分成两组,一组两人竞争,总有一个得到两只筷子
      wait(chopstick[i-1] mod 5);
      eat;
      signal(chopstick[i-1] mod 5);
      signal(chopstick[i]);
    }
    else {
      wait(chopstick[i-1] mod 5);
      wait(chopstick[i]);
      eat;
      signal(chopstick[i]);
      signal(chopstick[i-1] mod 5);
    }
  }while(TRUE);
}
void main(){
  cobegin
    for (int i=1; i<=5; i++){
      P(i);
    }
  coend
}

哲学家的变式

19年408考研题

43. (8 分)有 n(n≥3)位哲学家围坐在一张圆桌边,每位哲学家交替地就餐和思考。在 圆桌中心有 m(m≥1)个碗,每两位哲学家之间有一根筷子。每位哲学家必须取到一个碗和两 侧的筷子后,才能就餐,进餐完毕,将碗和筷子放回原位,并继续思考。为使尽可能多的哲学 家同时就餐,且防止出现死锁现象,请使用信号量的 P、V 操作[wait()、signal()操作]描述上 述过程中的互斥与同步,并说明所用信号量及初值的含义。

6.超市购物问题

问题描述(老师布置的一道作业题)

某超市里有一个收银员,且同时最多允许有n名顾客购物,将顾客和收银员看成是两类不同的进程。顾客进程进入超市时,如果超市中已经有n名顾客,他则排队等待;否则进入超市购物。购物结束后,顾客必须去收银台付款,等收银员收款后方能离开超市。试用信号量实现顾客与收银员进程的算法。

代码

//payment用来等待付费,receipt用来等待收费,Sn用于控制超市最多允许n名顾客
semaphore payment=0, receipt=0, Sn=n; 
void Customer(int i) {
    wait(Sn);
    进入超市购物;
    付费;
    signal(payment);
    wait(receipt);
    signal(Sn)
    离开超市;
}
void Cashier(){ 
    do {
        wait(payment);
        收费;
        signal(receipt);
    }while(true);
}
void main(){
    cobegin
        for (int i=1; i<=n; i++) {
            Customer(i);
        }
    Cashier();
	coend
}

PS:上面是老师给的答案,这个题我是真没想到是这样控制那n名顾客进入超市的…本来我还以为再设置一个等待队列的。。而且人数竟然设置为了信号量…

7.进程前趋关系问题

问题描述

再来一个用信号量实现进程前趋关系的题目,如下
在这里插入图片描述

代码

//就写b吧,a一个道理
p1(){S1();signal(a);signal(b);}
P2(){wait(a);S2();signal(c);signal(d);}
p3(){wait(b); S3; signal(e); signal(f);}
p4(){wait(c); S4; signal(g); }
p5(){wait(d); S5; signal(h); }
p6(){wait(e); S6; signal(i); }
p7(){wait(f); S7; signal(j); }   
p8(){wait(g); wait(h); wait(i); wait(j); S8;}       
main() {                         
    semaphore a,b,c,d,e,f,g,h,i,j;
    a.value=b.value=c.value=d.value=e.value=f.value=g.value=h.value=i.value=j.value=0;
    cobegin 
        p1();p2();p3();p4();p5();p6();p7();p8();
    coend 
}
  • 2
    点赞
  • 21
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值