在学习操作系统的同时,做了笔记加上了一些自己的备注和听课的内容,方便自己回顾知识点,如果能帮助到看文章的你那就更棒了。
目录
③互斥(让权等待等四个遵循的原则)
本文需要了解的问题有以下几个
- 为什么要引入进程同步的概念
- 不同的进程之间会存在什么样的关系
- 会遇到怎么样的问题
关于信号量和管程单独开一篇文章
1.进程同步的基本概念
在多道程序环境下,进程是并发执行的,每个进程之间都存在着不同的相互制约的关系。为了协调进程之间的相互制约的关系,引入了进程同步的概念(1)。
进程具有异步性(异步性是指,各并发执行的进程以各自独立的、不可预知的速度向前推进)的特征,如何解决异步问题,就是“进程同步”所讨论的内容。
①临界资源
多个进程可以共享系统中的各种资源,但是其中有些资源一次只能为一个进程所用(比如打印机)。我们把一次仅允许一个进程使用的资源称为临界资源。
对临界的资源的访问,必须互斥地进行,访问临界资源的那段代码称为临界区。
为了临界资源的正确使用,把临界资源的访问分成4个部分:
- 进入区。设置临界区的标志,这样可以当一个进程进入了进入区,其余进程无法进入。
- 临界区。访问临界资源的代码,又叫临界段。
- 退出区。将正在访问临界区的标志清除。
- 剩余区。代码中的其他部分。
②同步
同步也叫做直接制约关系,是协调它们的工作次序而等待、传递信息所产生的制约关系,这种关系源于它们之间的相互合作。
例如,有一根吸管,一杯奶茶和人。当吸管为空的时候人不能吃到奶茶里的珍珠会“阻塞”,一旦当珍珠送入吸管时,人才能被“唤醒”。反之,当吸管里都是珍珠时,奶茶被“阻塞”,只有当人吃掉一些的时候,才能“唤醒”奶茶。
③互斥
互斥也叫间接制约关系。当一个进程进入临界区使用临界资源时,另一个进程必须等待,当占用临界资源的进程退出临界区后,另一个进程才允许访问此临界资源。
为了禁止两个进程同时进入临界区,同步机制应遵循以下准则:
- 空闲让进。临界区空闲时,可以允许一个请求进入临界区的进程进入。
- 忙则等待。临界区有进程时,其他试图进入的必须等待。
- 有限等待。保证进程不会产生饥饿。
- 让权等待。当进程不能进入临界区时,应立即释放处理器,防止进程忙等。
两种资源共享的方式
互斥共享:一个时间段内只允许一个进程访问该资源。
同时共享:允许一个时间段内多个进程“同时”访问。
2.实现临界区互斥的基本方法
①软件实现
在进入区设置并检查一些标志来标明是否有进程在临界区,如果有了就通过循环检查进行等待,直到进程离开临界区后在退出区修改标志。以下有四种软件实现的方法,下面是学习这四个算法的提示。
- 理解各个算法的思想、原理。
- 结合“实现互斥的四个逻辑部分”,重点理解各算法在进入区、退出区都做了些什么。
- 分析各算法存在的缺陷(结合上面的“四个原则”)。
-
算法一:单标志法。设置一个公用整型变量turn。若turn为0,则允许P0进程进入临界区。该算法可确保每次只允许一个进程进入临界区。但两个进程必须交替进入临界区,若某个进程不再进入临界区,则另一个进程也将无法进入临界区(违背“空闲让进”)。
- P0进程
- while(turn!=0)//进入区
- critical section;//临界区
- turn=1;//退出区
- remainder section;//剩余区
- P1进程
- while(turn!=1)//进入区
- critical section;//临界区
- turn=0;//退出区
- remainder section;//剩余区
可以发现,如果我就P0进程进入并且结束退出,那么turn的值就是1,P1进程并不让他进入,那么下次P0就无法再次进入,因为turn就是1,违背了空闲让进。
-
算法二:双标志法先检查。算法基本思想是在每个进程访问临界区资源之前,先查看临界资源是否被访问,若正被访问,进程等待;否则,进程才进入自己的临界区。设置一个数据flag[i],如果第i个元素的值为FALSE,表示Pi进程未进入临界区,值为TRUE,表示Pi进程进入临界区。
- Pi进程
- while(flag[j])//进入区 ①
- flag[i]=TRUE;//进入区 ③
- critical section;//临界区
- flag[i]=FALSE;//退出区
- remainder section;//剩余区
- Pj进程
- while(flag[i])//进入区 ②
- flag[j]=TRUE;//进入区 ④
- critical section;//临界区
- flag[j]=FALSE;//退出区
- remainder section;//剩余区
优点:不用交替进入,可以连续使用;缺点:Pi和Pj可能同时进入临界区。按序列①②③④执行时,会同时进入临界区(违背“忙则等待”)。即在检查对方的flag后和切换自己的flag前有一段时间,结果都检查通过。问题出在检查和修改操作不能一次执行。
-
算法三:双标志法后检测。结合二的问题,先将自己的标志设置为TRUE,再检测对方的状态标志,若对方标志为TRUE,则进程等待;否则进入临界区。
- Pi进程
- flag[i]=TRUE;//进入区
- while(flag[j])//进入区
- critical section;//临界区
- flag[i]=FALSE;//退出区
- remainder section;//剩余区
- Pj进程
- flag[j]=TRUE;//进入区
- while(flag[i])//进入区
- critical section;//临界区
- flag[j]=FALSE;//退出区
- remainder section;//剩余区
两个进程几乎同时都想进入临界区时,它们分别将自己的标志设为flag设置为TRUE,并且同时检测到了对方的while,发现对方都要进,双方都进入不了,从而导致了“饥饿”的发生。(因为都进入不了,所以违背了空闲让进,导致了饥饿,违背了有限等待)
-
算法四:Peterson’s算法。为了防止两个进程为进入临界区无限期等待。设置了变量turn,每个进程在先设置自己的标志后再设置turn。这时,再同时检测另一个进程状态标志和不允许进入标志,以保证两个进程同时要求进入临界区时,只允许一个进入临界区。
- P1进程
- flag[1]=TRUE;turn=2;//进入区
- while(flag[2]&&turn==2);//进入区
- critical section;//临界区
- flag[1]=FALSE;//退出区
- remainder section;//剩余区
- P2进程
- flag[2]=TRUE;turn=1;//进入区
- while(flag[1]&&turn==1);//进入区
- critical section;//临界区
- flag[2]=FALSE;//退出区
- remainder section;//剩余区
P1设置flag=true表示P1想进入临界区,turn=2是检查P2是不是再临界区,如果符合while条件,则P1不能进入临界区。若P2不想要进入临界区,即flag[2]=false,循环条件不符合,则P1可以顺利进入。本算法结合了算法一和三。利用flag解决临界资源的互斥访问,利用turn解决“饥饿”现象。但是此算法并未遵循让权等待原则。进入区:1.主动争取 2.主动谦让 3.检查对方是否也想使用,且最后一次是谁想让。例如:先执行P1,那么flag[1]=TRUE;表示P1想访问,然后P1“谦让”,询问P2要不要访问,P2如果先执行flag[2]=TRUE,turn=1,P2就是想访问,那么P1检查P2想访问,但是P2说P1你可以先访问,因为turn设置成了1,所以最后一次是P2谦让给P1,那么P1就进入临界区。
②硬件实现方法
提示:
- 理解各方法的原理
- 了解各方法的优缺点
-
中断屏蔽方法
当一个进程使用处理机执行它的临界区代码,防止其他进程进入临界区最简单的方法是禁止一切中断的发生。因为CPU只在发生中断时引起进程切换,因为关掉或屏蔽中断能让临界区代码顺利执行完,进而保证互斥的正确实现。
- .
- .
- .
- 关中断;
- 临界区;
- 开中断;
- .
- .
- .
优点:简单、高效
缺点:不适用于多处理机,一个处理机再访问临界区,另一个处理机可能也会来访问临界区。只适用于操作系统内核进程,不适用于用户进程(因为开/关中断指令只能运行在内核态,这组指令如果能让用户随意使用会很危险。)
-
硬件指令方法
TestAndSet指令:这条指令是原子操作,即执行该代码时不允许被中断。其功能是读出指定标志后把该标志设置为真。
- boolean TestAndSet(boolean *lock){ //布尔型共享变量lock表示当前临界区是否加锁
- boolean old;
- old = *lock; //old用来存放lock原来的值
- *lock = true; //true表示加锁,false表示未加锁 无论之前是否加锁都将lock设置为true
- return old; //然后返回lock的值
- }
- while TestAndSet(&lock);//上锁并检查
- 进程的临界区代码段
- lock=false;//解锁
- 进程的其他代码;
Swap指令:该指令的功能是交换两个字(字节)的内容。
- Swap(boolean *a,boolean *b){
- boolean temp;
- Temp=*a;
- *a=*b;
- *b=temp;
- }
应为每个临界资源设置一个共享布尔变量lock,储值为false;在每个进程中再设置一个局部变量key,用于与lock交换信息。在进入临界区前,先利用Swap指令交换lock与key的内容,然后检查key的状态;有进程在临界区时,重复交换和检查过程,直到进程退出。利用Swap指令实现进程互斥的算法描述入下:
- key=true;
- while(key!=false)
- Swap(&lock,&key);
- 进程的临界区代码段;
- lock=false;
- 进程的其他代码段;
硬件方法的优点:使用于任意数目的进程,而不管是单处理机还是多处理机;简单、容易验证其正确性。支持进程内有多个临界区,只需为每个临界区设置一个布尔变量。
硬件方法的缺点:不能实现让权等待。从等待进程中随机选择一个进入临界区,有的进程可能一直选不上,从而导致“饥饿”。