2.4 进程的互斥
1.互斥的定义:对某个系统资源,一个进程正在使用它,另外一个想用它的进程就必须等待,而不能同时使用 。
2.临界区:进程中访问临界资源的那段程序代码称为临界区或临界段。使用同一临界资源的不同进程中的临界区称为同类临界区或相关临界区。
3.临界区使用原则:每次至多有一个进程处于临界区; 当有若干个进程欲进入临界区时,应在有限的时间内使其进入; 进程在临界区内仅逗留有限的时间。
空则让进:当无进程在互斥区时,任何有权使用互斥区的进程可进入。
忙则等待:不允许两个以上的进程同时进入互斥区。
多中择一:当没有进程在临界区,而同时有多个进程要求进入临界区,只能让其中之一进入临界区,其他进程必须等待。
等则有限:任何进入互斥区的要求应在有限时间内得到满足。
等则让权:当进程不能进入临界区时,应立即释放CPU,避免进程忙等待。
4.用上锁和开锁原语可以解决并发进程的互斥
(1)任何欲进入临界区的进程,必须先执行上锁原语。若上锁原语顺利通过,则进程可进入临界区;当完成对临界区资源的访问后再执行开锁原语,以释放该临界资源。
(2)即在相关进程的程序里由上锁和开锁原语紧夹着临界区,就能保证这些进程互斥地进入各自的临界区。
例如:
但是这种情况会使得CPU忙等,浪费了资源。
2.5信号量机制
1.信号量原理
两个或多个进程可以利用彼此间收发的简单的信号来实现“正确的”并发执行,一个进程在收到一个指定信号前,会被迫在一个确定的或者需要的地方停下来,从而保持同步或互斥。
2.个人理解:信号量简单理解就其实就相当于编程过程中所设置的flag,通过改变flag的值,对不同程序的运行进行控制,限制不同程序对于同一资源的访问次序。
P、V操作
P操作(wait),Proberen源自于荷兰语。原意:“测试”;
V操作(signal),Verhogen源自于荷兰语。原意:“增加”。
P操作:
既然是“测试”,那么测试过程中“临界资源”数量当然要减少,所以:
(1)S减1;
(2)若S≥0,则调用P(S)的进程返回,继续执行;
(3)若S<0,调用者进程调用阻塞原语Block(Q),把自己插入到信号量S的阻塞队列Q中(把相应的PCB连入该信号量队列的末尾,并放弃处理机,进入等待)。
V操作:
既然是“增加”,那么执行V操作之后,“临界资源”的数量应该有所恢复,所以:
(1)S加1;
(2)若S>0 ,则调用V(S)的进程继续执行,返回;
(3)若S<0 ,调用者进程调用唤醒原语Wakeup(Q)把信号量S的阻塞队列Q中的队首进程移出并唤醒,返回。
信号量机制实现互斥、同步
互斥:临界区前进行P操作,临界区后进行V操作
同步:目的让程序按照次序进行,比如:程序1、2执行后,程序4才能够执行。
实现进程互斥的过程中,根据系统资源的数量,对信号量的初始值进行 1 或者 更大 的赋值。
实现进程同步的过程中,信号量的初始值要设置为0。
经典实例:
生产者消费者问题:
生产者:每次生产一件产品放入仓库。消费者:每次从仓库中取出一件产品。仓库的大小为n。
在这个问题中,仓库就相当于是临界资源。
如果仓库满了,生产者不能继续生产(同步)。如果仓库空了,消费者不能够继续取产品(同步)。仓库一次只能允许一个生产者或者消费者进入,如果多个,对于仓库中空位不能够有效判断是否为空(互斥)。
互斥信号量:mutex=0;实现互斥访问
同步信号量:empty=n;表示空闲缓冲区数量
同步信号量:full=0;表示产品数量
productor(){
while(1){
P(empty);
P(mutex);
把产品放入缓冲区;
V(mutex);
V(full);
}
}
consumer(){
while(1){
P(full);
P(mutex);
从缓冲区取出产品;
V(mutex);
V(empty);
}
}
在这一过程中,首先判空、判满,判空之后在进行互斥信号量的改变。
该题目中隐含两条同步关系!!!!!!!