对信号量的临界区保护

来源:互联网 发布:淘宝店铺卖家版 编辑:程序博客网 时间:2024/06/05 04:23

一、概念介绍

临界区(critical section)在任意时刻只允许一个进程对共享资源进行访问。一次只允许一个进程进入的该进程的那一段代码。对于临界资源的访问必须是互斥进行的,也就是当临界资源被占用时,另一个申请临界资源的进程会被阻塞,直到其所申请的临界资源被释放。而进程内访问临界资源的代码被称为临界区。

while(TURE){    进入区    临界区    退出区    剩余区}

这里写图片描述

信号量(semaphores)允许多个进程(也可以是多个线程)同时使用共享资源。它指出了同时访问共享资源的最大进程数目。它允许多个进程在同一时刻访问同一资源,但是需要限制在同一时刻访问此资源的最大进程数目。
信号量除初始化外,仅能通过两个标准的P、V原子操作来访问。量用来记录,信号用来sleep和wakeup。
P的名称来源于荷兰语proberen,即test。
V的名称来源于荷兰语verhogen,即increment。

struct semaphore{   int value;//记录资源个数   PCB *queue;//记录等待在该信号量上的进程}P(semaphore s);//消费资源V(semaphore s);//产生资源

P操作

P(semaphore s){   s.value--;   if(s.value<0){     sleep(s.queue);   }}

V操作

V(semaphore s){  s.value++;  if(s.value<=0){     wakeup(s.queue);  }}

可以用临界区保护信号量,用信号量实现同步。

二、生产者消费者问题引入

共同修改信号量引出的问题:
这里写图片描述
第j次执行的empty结果就不对了。
错误由多个进程并发操作共享数据引起,且和调度顺序有关,难于发现和调试。

三、解决问题的直观想法

在写共享变量empty时阻止其他进程也访问empty。
这里写图片描述

四、临界区代码的保护原则

(1)互斥进入:如果一个进程在临界区中执行,则其他进程不允许进入。这些进程间的约束关系称为互斥,且这也保证了是临界区。
(2)有空让进:若干进程要求进入空闲临界区时,应尽快使一进程进入临界区。
(3)有限等待:从进程发出请求到允许进入,不能无限等待。

五、进入临界区的尝试

(1)轮换法:

这里写图片描述
互斥进入满足。
有空让进不满足,P0完成后不能接着再次进入,尽管进程P1不在临界区。

(2)标记法:

这里写图片描述

有限等待不满足。

(3)Peterson算法:

结合标记和轮转两种思想。
Peterson算法是一个实现互斥锁的并发程序设计算法,可以控制两个进程访问一个共享的单用户资源而不发生访问冲突。
这里写图片描述

互斥进入满足:如果两个进程都进入,则flag[0]=flag[1]=true,turn==0==1,矛盾。
有空让进满足:如果P1不在临界区,则flag[1]=false,或者turn=0,都能使p0进入。
有限等待满足:P0要求进入,flag[0]=true,后面的p1不可能一直进入,因为P1执行一次就会让turn=0。

(4)面包店算法:

仍然是标记和轮转的结合,不过这次是解决多个进程访问资源冲突的问题了。
轮转:每个进程都获得一个序号,序号最小的进入。
标记:进程离开时序号为0,不为0的序号即标记。
这里写图片描述

互斥进入满足:Pi在临界区内,Pk试图进入,一定有(num[i],i)<(num[k],k),Pk循环等待。
有空让进满足:如果没有进程在临界区中,最小序号的进程一定能够进入。
有限等待:离开临界区的进程再次进入一定排在最后,所以任一个想进入的进程至多等n个进程。

为实现进程互斥地进入自己的临界区,有软件方法,也有硬件方法。上面介绍的都是软件方法。

0 0