前言
经典进程同步问题:生产者-消费者问题、哲学家进餐问题、读者-写者问题,通过信号量来实现进程之间的同步。
生产者-消费者问题
1.利用记录型信号量解决生产者-消费者问题
假定在生产者和消费者之间的公用缓冲池中具有n个缓冲区,这时可利用互斥信号mutex实现诸进程对缓冲池的互斥使用;利用信号量empty和full分别表示缓冲池中空缓冲区和满缓冲区的数量。又假定这些生产者和消费者相互等效,只要缓冲池未满,生产者可将消息送入缓冲池;只要缓冲池未空,消费者便可从缓冲池中取走一个消息。
|
|
2.利用And信号量解决生产者-消费者问题
|
|
哲学家进餐问题
五个哲学家共用一张圆桌,分别坐在周围的五个椅子上,在圆桌上有五个碗和五只筷子,他们的生活方式是交替的进行思考和进餐。平时,一个哲学家进行思考,饥饿时便试图用其左右最靠近他的筷子,只有在他拿到两只筷子时才能进餐。进餐完毕,放下筷子继续思考。
1.利用记录型信号量解决哲学家进餐问题
经分析,放在桌子上的筷子时临界资源,在一段时间内只允许一位哲学家使用。为了实现对筷子的互斥使用,可以用一个信号量表示一只筷子,由这五个信号量构成信号量数组。其描述如下:
|
|
所有信号量均被初始化为1,第i为哲学家的活动可描述为:
|
|
假如五位哲学家同时各自拿起左边的筷子时,就会使五个信号量chopstick为0,当他们再试图去拿右边的筷子时,都将因无筷子可拿而无限期地等待。对于这种死锁问题,可采取一下几种解决方法。
首先给出两个断言:
(1)系统中有N个并发进程。若规定每个进程需要申请2个某类资源,则当系统提供N+1个同类资源时,无论采用何种方式申请资源, 一定不会发生死锁。分析:N+1个资源被N 个进程竞争, 由抽屉原理可知, 则至少存在一个进程获2个以上的同类资源。这就是前面提到的哲学家就餐问题中5个哲学家提供6支筷子时一定不会发生死锁的原因。
(2)系统中有N个并发进程。若规定每个进程需要申请R个某类资源,则当系统提供K=N*(R-1)+1个同类资源时,无论采用何种方式申请使用,一定不会发生死锁。分析:在最坏的情况下,每个进程都申请到R-1个同类资源, 此时它们均阻塞。 试想若系统再追加一个同类资源, 则 N 个进程中必有一个进程获得R个资源,死锁解除。
(1)破坏请求保持条件
利用原子思想完成。即只有拿起两支筷子的哲学家才可以进餐,否则,一支筷子也不拿。
解法一:利用AND机制实现第i位哲学家的活动描述为:
|
|
解法二:利用记录型信号量机制实现在初始化中增加一个信号量定义:semaphore mutex=1:
该方法将拿两只筷子的过程作为临界资源,一次只允许一个哲学家进入。
第I位哲学家的活动描述:
|
|
(2)破坏环路等待条件
解法一:奇数号哲学家先拿他左边的筷子,偶数号哲学家先拿他右边的筷子。这样破坏了同方向环路,一个哲学家拿到一只筷子后,就阻止了他邻座的一个哲学家吃饭。按此规定,将是1、2号哲学家竞争1号筷子;3、4号哲学家竞争3号筷子。算法描述如下:
1)第i个哲学家的活动:
|
|
解法二:至多允许四位哲学家进餐,将最后一个哲学家停止申请资源,断开环路。最终能保证有一位哲学家能进餐,用完释放两只筷子,从而使更多的哲学家能够进餐。增加一个信号量定义semaphore count=4:算法描述第1个哲学家的活动:
|
|
读者-写者问题
允许多个进程同时读一个共享对象,但不允许一个write进程和其他reader进程或writer进程同时访问共享对象。所谓读者-写者问题是指:保证一个writer进程必须与其他进程互斥地访问共享对象的同步问题。
1.记录型信号量解决读者-写者问题
为实现reader和writer之间的互斥而设置一个互斥信号量wmutex。同时,增加一个count计数器,用来记录reader进程的个数,reader进程执行时,并且count==0时,此时wait(wmutex),禁止写进程去写,然后++count;reader进程执行完毕后,–count,如果count ==0时,此时表示无reader进程,则signal(wmutex),允许writer去写。同时由于reader进程互斥的共享count,所以我们设置一个rmutex来互斥访问count。
|
|
2.利用信号量集机制解决读者-写者问题
Swait((S,1,0):是一种很特殊且很有用的信号量操作。当S>=1时,允许多个进程进入某特定区;当S变为0后,将阻止任何进程进入特定区。换言之,它相当于一个开关。
这里我们增加一个限制,即最多允许RN个读者同时读。为此我们引入一个信号量L,并赋予其初值为RN,通过执行Swait(L,1,1)来控制读者的数量。
|
|