如何实现进程同步
假设有两个代码块S1,S2顺序进行(先S1后S2),在在S1和S2之间设个信号量S,则先V后P
分析:
信号量初始设置为0,先V让它变为1才能在P那里不阻塞进行,如果先P让信号量变为-1则会阻塞
结论:
先V后P
生产者消费者问题:
问题描述:
PV操作分析步骤:
确定进程,确定同步和互斥关系
同步互斥关系:
生产者与消费者对缓冲区进行访问(互斥,设信号量mutex)
当盘子满的时候,先让消费者消耗再生产(同步,设信号量full)
当盘子空的时候,先让生产者生产在消耗(同步,设信号量empty)
理解方法:
对于full信号量,假设full为1,不能再往里放东西了,这个full的对象是生产者,所以生产者先执行,因此生产者V(full);
对于empty信号量,假如empty=1,消费者不能在消费,对象是消费者,故消费者实行V(empty)
解决方法:
PV顺序问题:
实现互斥的P操作一定要放在实现同步的P操作之后,否则会死锁
多生产者消费者问题:
问题描述:
PV操作分析步骤:
确定进程,确定同步和互斥关系
同步互斥关系:
理解方法:
对于apple信号量,假设apple为1,父亲不能再往里放东西了,这个apple的对象是父亲,所以父亲先执行,因此父亲V(apple);
对于orange信号量,假设orange为1,母亲不能再往里放东西了,这个orange的对象是母亲,所以母亲先执行,因此母亲V(orange);
对于plate信号量,假如plate=1,孩子们要先拿水果水果,对象是孩子,故孩子实行V(plate)
解决方法:
PV顺序问题和一些要点:
实现互斥的P操作一定要放在实现同步的P操作之后,否则会死锁
当缓冲区为1时,不用互斥量(不过以防万一还是可以加上)
吸烟者问题:
问题描述:
PV操作分析步骤:
确定进程,确定同步和互斥关系
同步互斥关系:
解决方法:
PV顺序问题和一些要点:
实现互斥的P操作一定要放在实现同步的P操作之后,否则会死锁
当缓冲区为1时,不用互斥量(不过以防万一还是可以加上)
读者,写者问题:
问题描述:
PV操作分析步骤:
确定进程,确定同步和互斥关系
同步互斥关系:
解决方法:
方法1:(设置一个互斥量rw,让写进程与读进程互斥访问缓冲区)
方法1问题所在:
假设有两个进程同时读,在第一个进程还未让count++,第二个读进程来临,发现count为0,想上锁,但是因为依旧上过锁了发生阻塞。
方法一问题分析:
对于count变量的检查和赋值没有一气呵成,所以对count的访问也需要时互斥的
方法2:(对count设置一个信号量mutex,实现对count访问互斥)
方法2问题所在:
假设一直持续不断有读文件进程,则rw一直被上锁,当有写文件过来时,无法访问缓冲区,出现“饿死”,
方法2问题分析:
对于写操作没有设置优先级,导致出现饿死
方法3:(设置一个信号量w,让先来的操作无论是写还是读都有优先级)
分析总结:
- rw信号量实现了读写互斥,以及读进程之间先来的有优先级,且读进程之间不互斥;
- mutex信号量实现了对count修改的一气呵成;
- w信号量实现了先来的进程(无论读写)有优先级
哲学家吃饭问题:
问题描述:
PV操作分析步骤:
确定进程,确定同步和互斥关系
同步互斥关系:
解决方法:
方法:
方法问题所在:
假设多个哲学家进程并发执行,有可能同时拿起左边的筷子,然后等待右边的筷子,造成死锁
方法问题分析:
没有对多个并发的程序赋予一定的优先级,导致死锁
方法改善:(设置一个信号量mutex,对先吃饭的哲学家进程赋予优先级)
分析总结:
- 筷子信号量数组实现了对哲学家对于筷子的互斥关系
- mutex信号量实现了哲学家进餐的优先级,避免死锁
问题总结
- 当分析问题时出现有饿死或者死锁关系的时候,再设置一个信号量给进程之间赋予优先级,可能解决
- 当某些操作不能一气呵成造成一些阻塞现象时,也可以考虑再设置一个信号量实现对操作的一气呵成