进程互斥
定义:由于各进程要求使用共享资源,而这些资源具有排他性,各进程竞争使用这些资源,成为进程互斥。
竞争条件:两个或多个进程读写某些共享数据,而最后的结果取决于进程运行的精确时序。
临界资源:某些资源只允许一个进程使用。
临界区:进程对某个资源实施操作的程序片段。
忙等待:进程在得到临界区之前,持续测试而不做其他事。
一、进程互斥方案
1、软件方案
1.1、Dekker算法
引入turn变量。
首先设 int turn = 1;
1、当进程P与Q同时完成第5与25行的赋值后,同时进入循环执行。
2、此时判断turn的值,此时初值为1,Q进程进入临界区,P进程则等待。
3、当Q进程完成临界区代码后,将turn赋值为1并且qturn为false。若此时
P进程执行的话,将不会等待,跳出循环进入临界区执行。
4、此时进程互斥得到解决。按顺序执行了。
1.2、Peterson算法(具有忙等待的缺点)
二、信号量及PV操作
信号量是一个特殊的变量,用于进程间传递信息的一个整数值。
pv操作针对进程互斥的实例:
1、假设p1、p2、p3同时需要访问共享数据。
2、当p1率先进入p(mutex)时,会使得count变为0,不小于0,所以会直接进入临界区。
3、此时如果p2、p3进入p(mutex)时,由于count已经小于0,所以会进入信号量的等待队列。
4、在p1执行完临界片段的代码后,count自增,发现还是小于0,所以会将等待队列里面的进程调度出来,使其变成就绪态,并插入到就绪队列。
三、信号量解决生产者、消费者问题
情况一、设此为一个有限缓冲区,并且初始状态下,缓冲区为空。
若生产者首先执行,在执行P(&empty)的时候,empty的值不小于0,所以会直接进入临界区进行插入缓冲区操作。
若消费者首先执行,在执行到P(&full)的时候,由于小于full--之后小于0,所以会进行等待操作(即将消费者进程进入等待队列中)。
情况二、设缓冲区存在数据,但为装满。
若当生产者执行P(&empty)的时候,此时判断empty大于0,之后转入消费者执行,此时消费者的full也是大于0的,二者同时转入临界区执行。但这是禁止的。所以在临界区代码处增加了p(&mutex)语句。所以两个P操作是不能调换位置的。
四、信号量解决读者~写者问题
满足条件:
1、允许多个读者同时执行读操作。
2、不允许多个写者同时操作。
3、不允许读者、写者同时操作。
实例:现在假设读者正在读数据,此时来个一个写者,只能挂起等待。之后又来了一个读者,则会让此读者直接进入读取。但是如果大量读者到来,会使得写者无法执行。为了避免这种行为,在一个读者到达的时候,如果发现前面有一个写者正在等待,则这个读者及之后的读者都会挂起等待。直到写者完成写的操作为止。代码如下: