操作系统学习 - 经典的进程同步互斥若干问题

1. 生产者-消费者问题

问题模型:
系统中有一组生产者进程和一组消费者进程,生产者进程每次生产一个产品放入缓冲区,消费者进程每次从缓冲区中取出一个产品并使用(产品:某种数据)。

生产者、消费者共享一个初始为空、大小为 n 的缓冲区。

  • 只有缓冲区没满时,生产者才能把产品放进去,否则必须等待(同步关系)。
  • 只有缓冲区不空时,消费者才能取出产品,否则必须等待(同步关系)。
  • 缓冲区必须是互斥访问的,是临界资源(互斥关系)。

在这里插入图片描述
要注意各种 P 操作的先后顺序(因为P操作会让进程阻塞),否则容易出现“死锁”现象。
在这里插入图片描述

  • 在这个问题模型中,要注意的是同步要在互斥前边

多生产者 - 多消费者

2. 吸烟者问题

问题模型:
生产者可以往桌子上放不同的材料,三个吸烟者需要拿到自己对应的材料,才可以完成吸烟动作。吸烟完成后,通知生产者,生产者才放下一个材料,三个吸烟者轮流吸烟。

主要的同步、互斥关系:

  • 桌子是一个容量为 1 的缓冲区,要互斥访问。(互斥关系)
  • 桌子上有组合一,第一个人才可以抽烟。(同步关系)
  • 桌子上有组合二,第二个人才可以抽烟。(同步关系)
  • 桌子上有组合三,第三个人才可以抽烟。(同步关系)
  • 每个吸烟者吸烟结束,供应者才可以将下一个组合放在桌子上。(同步关系)
    在这里插入图片描述
    注意这里边,互斥的关系,并没有单独设置一个信号量,因为4个负责同步的信号量,同一时刻只会有一个有值。
    • 吸烟者问题为解决“可以生产多个产品的单生产者”问题提供了一个思路。

3. 读者-写者问题

问题模型:
在这里插入图片描述

  • 多个读进程可以同时读,不会出问题。
  • 读写进程一起访问共享文件的话,会导致读进程读的并不是自己想要的那份(被写进程改了)
  • 多个写进程一起写入共享文件,可能导致数据被覆盖。

综上:

  • 只可以多个读进程一起。
  • 写进程执行的时候,其他的写进程和读进程都不能访问。
  • 读进程执行的时候,写进程不能访问。

关系如下:

  • 写 - 写(互斥)
  • 读 - 写(互斥)
    在这里插入图片描述
    读写者模式的精巧之处:

上边图里对读进程的设计中,如果没有count变量记录读进程的数量的话,会导致读进程与读进程之间也是互斥的,这并不是我们希望的。如果像上图中的设计,当多个读进程去读共享文件时(有先后顺序),只有访问共享文件的进程才会上锁,其他的读进程都不会进行上锁操作,因为通过count变量可以知道已经有读进程在读了,此时去读的话,并不会和写进程冲突,可以放心的读。同理,只有最后一个读完文件的读进程才会执行解锁操作,因为比它先读完的那些进程不能执行解锁操作,一旦解锁,写进程就会开始写入,就会造成读写冲突。

上边的这种设计存在一个问题,如上图的左下角所示,如果两个读进程并发的执行在读count变量时,都为0,会导致其中一个上锁,另一个读进程被阻塞,这是不可以的。所以再对count变量进行互斥访问,加一个mutex。


可见,上边这种方式是“读进程优先”的,只要有读进程在读,那写进程就会一直被阻塞,可能“饿死”。
再加入一个信号量 w,把写进程的优先级提一提。
在这里插入图片描述
引入 信号量w以后,并发执行的情况。

  • 读者1->读者2

    读者1读完以后,会对mutex和w都执行V操作,所以读者2可以正常读文件。

  • 写者1->写者2

    多了一个互斥信号量,所以也不会有影响。
    *写者1->读者1

    写者1执行后,w和rw上锁,此时如果有读者进程尝试访问,w信号量会让该读进程阻塞。

  • 读者1->写者1->读者2

    读者1在读的时候,写者1尝试访问,读者1会被w阻塞,当读者1执行了 V(w) 以后,写者1会对w上锁,然后被rw阻塞,如果此时,读者2尝试访问,因为写者1对w上了锁,所以读者2会被w阻塞掉。等到读者1执行了V(rw)以后(此时count一定为1,因为读者2被阻塞着),写者1可以对rw上锁,开始正常的写入。等待写者1操作结束,对rw和w解锁后,读者2就可以正常的进行了。
    这就避免了之前,写进程饥饿的问题。

  • 写者1->读者1->写者2

写者1对w和rw上锁后,开始写文件操作,此时读者1尝试访问,被w信号量阻塞,此时再有写者2尝试访问,也被w信号量阻塞,当写者1完成任务,释放rw和w后,因为读者1先于写者2上锁排队,所以w信号量被解锁后,读者1开始执行,写者2依然开始被阻塞着。

这种方法相对读者和写者都相对公平。牛逼!

总结:

  • count服务于读进程,保证读进程不互斥,mutex用于保证对count的互斥访问。
  • w用于解决写进程饥饿。

4. 哲学家进餐问题

问题模型:
在这里插入图片描述

  • 下面这种方案是不合理的,会存在死锁现象,所有的哲学家都等待自己右手边的筷子,又没有人放下自己手中的筷子。 在这里插入图片描述
    两个解决死锁问题的思路:
  1. 限制最多只允许4个哲学家进餐。
  2. 要求奇数号的哲学家先拿左手边筷子,偶数号哲学家先拿右手边筷子。
  3. 要求有人拿筷子的时候,其他人不能拿。(有书上说的是,当左右筷子都可用时才允许拿起来)

第三种方法:
在这里插入图片描述
情况说明:

  • 0号想吃饭,拿起左边筷子时,此时进程切换,2号想吃饭了,2号被mutex阻塞,只能等到0号吃完,2号采可以拿筷子、吃饭。
  • 0号拿起左右筷子,对mutex解锁后,0号开始吃饭,1号此时只能拿起左筷子,拿右筷子时被阻塞,如果此时2号也想吃饭,但它一根筷子也拿不了(即使左右都有筷子可用),因为被mutex阻塞了。只能等1号吃完,它再吃。
  • 0号拿起左右筷子,对mutex解锁后,0号开始吃饭,4号想吃饭,只能拿起左侧的筷子,拿右筷子时被阻塞
    哲学家进餐问题的关键在于解决进程死锁
    哲学家进餐问题的关键在于解决进程死锁
    哲学家进餐问题的关键在于解决进程死锁
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值