进程同步问题(1)——生产者,消费者 & 读者,写者问题

今天看操作系统的时候,在进程管理一章又看到了经典的进程同步问题。进程同步问题确实比较复杂,因为要保证进程推进顺序合法,可能会使用到多个信号量,而且很多p,v操作的顺序也不

可颠倒。好在进程同步有几个经典问题,如果搞清楚了,对其他问题也可以举一反三。

生产者消费者问题:
分析:1.生产者消费者共用一个缓冲区,生产者向其中投入产品,消费者从中取出产品,并消费。所以需要定义一个缓冲区,这里用数组这种数据结构便可以。
2.设置两个记录性信号量,一个说明空缓冲区数量,用empty表示,初值为n,一个说明满缓冲区数量,用full表示,初值为0
3.因为生产者消费者不唯一,所以需要定义一个互斥信号量mutex,初值为1.
程序如下:
Semaphore empty = n;
Semaphore full = 0;            //empty与full是此消彼长的关系,为了方便,设置两个信号量
Semaphore mutex = 1;
Array Buffer[0...n-1];
int index = 0;  //用来记录缓冲区当前的索引
Producer() {
    while(true) {
        p(empty);
        p(mutex);
        produce a product p;
        Buffer[index] = p;
        index++;
        V(mutex);
        V(full);
    }
}
Consumer(){
   while(true) {
       p(full);
       p(mutex);
       consume Buffer[index];
       index--;
       V(mutex);
       V(empty);
   }
}
需要注意的问题:p(mutex)与p(full)/p(empty)顺序不能颠倒,V(mutex)与v(full)/v(empty)顺序则随便。

读者写者问题:(读者优先)
描述:可以允许多个读者同时读;读者和写者之间必须互斥;读者优先,所以只有读者数目为0时候,写者才能够写
思路:1.信号量解决的是互斥的问题,但是写者何时能写,是一个条件判断,需要判断读者数目,所以设置一个变量readcount,记录读者的个数。
2.对读者的数量更新时,需要设置一个信号量用于互斥,防止多个读者同时读,从而同时更新读者数量
3.读者与写者之间互斥,所以也需要互斥信号量
int readcount = 0;
semaphore rwmutex = 1;
semaphore rmutex= 1; //用于读者进程更新readcount时候互斥
reader() {
  p(rmutex);
  readcount++;
  if(readcount == 1) p(rwmutex);      //只要读者数量达到1的时候,将使用rwmutex互斥,阻止新的写者进入
  v(rmutex);
  读数据;
  p(rmutex);
  readcount--;
  if(readcount == 0) v(rwmutex);
  v(rmutex);
}

writer() {
 p(rwmutex);
 写数据;
 v(rwmutex);
}

读者写者问题:(写者优先)
描述:与读者优先的区别是,一旦有写者,则后续读者需要等待,唤醒时优先唤醒写者。
思路:关键问题是处理:如果当前有一个读者或者写者在读/写,怎样让排队的那些读者/写者保持写者优先。
semaphore rwmutex = 1;
semaphore rmutex = 10;     //初始值设为10,表示最多允许10个读者同时读
reader()
{
      p(rwmutex);          //用于读写互斥,如果有写者在写数据或者在排队,则读者就进不去
      p(rmutex);            //占用一个读者名额
      v(rwmutex);
      读数据;
      v(rmutex);        
}
writer()
{
     p(rwmutex);                                   //禁止新的读者进入
     for(i=1; i  < 10; i++) {
         p(rmutex);                                 //只要有一个写者进程进入时,第一件事就是将所有读者的名额全部占用,那些还没占用的读者名额会被立即占用,而正在读数据的读者,在释放了名额之后,名额会被立即占用
    }
    写数据;
    for(i = 1; i < 10; i++) {
        v(rmutex);                                   //恢复rmutex的值为10
    }
    v(rwmutex);                                    
}
以后有时间再继续分析其他几个经典同步问题

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值