生产者——消费者问题
问题描述:一组生产者,一组消费者,大小为n的缓冲区,只有缓冲区没有满的时候生产者才能往里面放东西,之后缓冲区不为空时消费者才才能消费东西,缓冲区属于临界资源不可同时访问。
关系分析:生产者和消费者不能同时进行操作存在互斥关系,消费者和生产者具有同步关系,消费者消费了之后才能生产,生产者生产了之后才能消费。
思路:只有生产者和消费者两个进程,他们存在互斥和同步
信号量:信号量mutex作为互斥信号量,用于控制互斥访问缓冲区,互斥信号量初始值为1:信号量full用于记录当前缓冲区是否满,初值为0,信号量empty用于记录当前缓冲池中的空,初值为n
注意:互斥信号量不可放在同步信号量之前,互斥信号量若放在同步信号量之前,互斥信号量执行之后另外一个进程就不可操作,若在这个时候同步信号量条件不满足,需要另外一个进程来释放缓冲区或者添加缓冲区,但由于互斥信号量已经执行,这个时候进程双方都被制约,会导致死锁。
多生产者多消费者问题
问题描述:两个生产者两个消费消费者,一个大小为1的缓冲区(临界资源),缓冲区满了生产者就不能添加东西进去,缓冲区有东西时消费者才能消费,生产者a的东西只有消费者a能用,生产者b的东西只有消费者b能用。
关系分析:因为每次只能放一个东西,所以生产者存在互斥关系,消费者a和生产者a存在同步关系,消费者b和生产者b存在同步关系,两个消费者不存在关系,只和缓冲区里面的东西决定是否可以消费。
信号量设置:plate设置为互斥信号量为1表示可以放入,a表示缓冲区中是否有a产品,a=1表示可以取出,b表示缓冲区是否有b产品,b=1表示可以取出,
注意:发现代码里面并没有使用互斥信号量,这是因为缓冲区只有1个位置,缓冲区只存在有和没有两种状态,而消费者有只会消费自己的产品,导致盘中里面只有可能有a产品、有b产品和没有产品三种情况下才有可能进行操作,每种情况 不可能同时存在,所以进程之间自然就不会同时操作,进而不需要互斥信号量
吸烟者问题(单生产者——多消费者问题)
问题描述
组合一:纸和胶水
组合二:烟草和胶水
组合三:烟草和纸
关系:有组合一第一个抽烟者才会取东西,有组合二第二个抽烟者才会取东西,有组合三第三个抽烟者才会取东西,桌子上没有东西供应者才能提供材料
信号量设置:信号量offer1,offer2,offer3,分别表示三种组合,信号量finish用于互斥进行抽烟动作
注意:这个问题下也没有用互斥信号量,原理和上一个一样,因为只会桌子上没有东西,有第一组合,有第二组合,有第三组合,这4种情况只会有一个进程操作,所以不可能出现同时操作的情况,所以就不需要互斥信号量
读者——写者问题
问题描述
思路:写者和任何进程都互斥,读者在实现与写者互斥的过程中,还需要和其他读者同步,需要用到一个计数器,有读者的时候写者不能写
信号量设置:count为计数器,用来记录当前读者的数量,初值为0,设置mutex为互斥信号量用于保护count变量时的互斥,设置rw用于保证读者和写者之间的互斥
mutex的作用,由于读进程判断数量的过程中可能会发生进程切换,所以需要一个信号量让在判断数量的过程中不能发生进程切换,这个算法如果出现有源源不断的读进程进来写进程就会被饿死。
改进方案:
上面说的问题是因为,在写者等待读者读完的过程中,会出现新的读者进入,导致写进程被”插队“,那么问题就在于,读进程读的过程中,写进程被阻塞了,而新的读进程依然可以读操作,那么我们只需要在有写进程被阻塞的情况下,把新的读进程也阻塞掉,这样新的读者进程就不会出现(插位)的现象,我们在读进程增加新进程的过程中,加一对互斥变量w,写进程在第一个读进程读取的时候,写入消耗一个w信号量,然后到了rw的时候又被阻塞,由于写进程消耗了一个w信号量,导致新的读进程,在p(w)的时候被阻塞,当第一个进程读写完rw释放,写进程就可以运行,写进程运行结束释放w,第二个读进程也可以进行读操作,而在没有写进程写入的情况下,第二个读进程在第一个读进程读取的时候也可以进行读取,完成了并发,写进程在写操作时,其他操作也不能操作完成了互斥。
哲学家问题
思路一:让哲学家在想吃饭的时候先拿起左边的筷子再拿起右边的筷子,吃完饭之后放下左边的筷子后放下右边的筷子,但是如果五个哲学家同时想吃饭了,同时拿起了左边的筷子,这个时候哲学家门想要拿起右边的筷子的时候,发现已经被占用了,就会出现死锁现象。
为了解决这个问题,方案一:可以限制哲学家同时进餐的人数,最多只能允许4个哲学家同时进餐,这样至少会有一个人能吃到东西
方案二:要求奇数号的哲学家先拿起左边的筷子,拥有偶数号的哲学家先拿起右边的筷子,这样导致在拿第一个筷子的时候就决定了谁能吃到饭,没有拿到筷子的人在拿第一个筷子的时候就被阻塞了,而拿到筷子的人的第二根筷子没人拿,可以直接吃饭不会发生阻塞
方案三:当哲学家可以拿起两根筷子的时候才允许拿起筷子,并且它在拿筷子的过程中,其他哲学家不能拿筷子,这样在哲学家拿筷子的过程中是左右一气呵成的。
管程
是一种高级的同步机制,比pv操作用起来轻松,管程和pv一样都是为了实现进程之间的互斥和同步,管程中的数据只能由管程中的函数调用,每次仅仅允许一个进程在管程内执行某个内部过程,这样就保证了互斥