进程的同步
我们把异步环境下的一组并发进程因直接制约而互相发送消息、进行互相合作、互相等待,使得各进程按一定的速度执行的过程称为进程间的同步。
进程需要同步的条件
- 进程是并发的
- 两(多)个进程之间存在相互制约关系
- 间接相互制约关系(资源共享关系)
- 多进程共享资源,例如各进程争用一台打印机,这时如各进程随意使用打印机,会造成打印机结果交织在一起难以区分。
- 多个进程彼此无关,完全不知道或只能间接感知其它进程的存在。
- 系统须保证诸进程能互斥地访问临界资源。
- 系统资源应统一分配,而不允许用户进程直接用。
- 直接相互制约关系(相互合作关系)
- 在某些进程之间还存在合作关系,例如某一个程序的输入、计算、打印三个程序段作为三个进程并发执行,由于这三个进程间存在着相互合作的关系,即先输入再计算、最后再打印的关系。
- 系统应保证相互合作的诸进程在执行次序上的协调和防止与时间有关的差错。
- 间接相互制约关系(资源共享关系)
临界资源
在一段时间内只允许一个进程访问的资源称为临界资源或独占资源,许多硬件资源如打印机、磁带机等,和变量及表格等都属于临界资源(Critical Resouce)。也有一些软件资源,也只允许一个进程以独占的方式访问,称为软件临界资源。
显然,当多个进程共享临界资源时,进程之间就要进行同步。
- 如何访问临界资源
- 设置临界区(critical section) -----每个进程中访问临界资源的那段代码
- 保证诸进程互斥地进入自己的临界区
- 每个进程在进入临界区之前,应先对欲访问的临界资源进行检查,只有当临界资源当前没有被别的进程使用时才允许其进入临界区
进程同步机制准则
-
空闲让进:
当无进程处于临界区时,表明临界资源处于空闲状态,应允许一个请求进入临界区的进程立即进入自己的临界区,以有效地利用临界资源 。
-
忙则等待:
当已有进程进入临界区时,表明临界资源正在被访问,因而其它试图进入临界区的进程必须等待,以保证对临界资源的互斥访问。
-
有限等待:
对要求访问临界资源的进程,应保证在有限时间内能进入自己的临界区,以免陷入“死等”状态。
-
让权等待:
当进程不能进入自己的临界区时,应立即释放处理机,以免进程陷入“忙等”状态。
进程同步机制----信号量机制
信号量:一个用于表示资源数目的整型量S,当进程请求一个单位的资源时,根据当前的信号量来决定是否需要等待。
-
整形信号量
仅能被两个标准的原子操作wait(s)和signal(s)亦即P/V操作来访问。
- 原子操作是不可分割的,在执行完毕之前不会被任何其它任务或事件中断。
- P、V操作是荷兰语通过和释放的意思。
-
wait(S):当进程请求一个单位的资源时执行,检查信号量是否大于0,若是,就将S减1,若不是,则等待。
wait(S): while S<=0 do noop;# noop表示置空 S:=S-1;
-
signal(S):当进程释放资源时执行,将S加1:
signal(S): S:=S+1;
缺陷:没有解决让权等待
-
如何解决这个问题?
当没有可用资源时,进行自我阻塞,放弃处理机,而不是等待处理机的时间片用完
资源一旦被释放,要唤醒被阻塞的进程
所有被阻塞的进程都要被合理记录
-
记录型信号量
定义记录型信号量,它包含两个数据项,一个是当前可用的资源数,一个是用于记录当前被阻塞的进程的链表
-
wait(S)操作:
procedure wait(S) var S:semaphore; begin S.value:=S.value-1; if S.value<0 then block(S.L); end
-
signal(S)操作:
procedure signal(S) var S: semaphore; begin S.value:=S.value+1; if S.value<=0 then wakeup(S.L); end
定义信号量semaphore代表可用资源实体的数量。又叫信号灯。
当≥0,代表可供并发进程使用的资源实体数
当<0,表示正在等待使用该资源的进程数
当=1,表示只允许一个进程访问临界资源,此时的信号量即为互斥信号量,用于进程互斥。
-
-
AND型信号量
出现原因:一些应用往往需要两个或多个共享资源,而不是前述的一个资源。进程同时要求的共享资源越多,发生死锁可能性越大。
如图所示:
进程A和B处于僵持状态,在无外力作用下,两者都将无法从僵持状态中解脱出来,我们称此时的进程A和B已进入死锁状态。
解决思想:一次性分配给进程所需资源,用完一起释放。Wait操作时对它所有需要的资源都要判断。只要尚有一个资源未能分配给进程,其它所有可能为之分配的资源也不分配给它。
Swait(S1,S2,…,Sn) if S1>=1 and … and Sn>=1 then for i:=1 to n do Si:=Si-1; endfor else # 否则将进程阻塞在第一个不能满足资源信号量的队列中并且重新将PC计数器重新指向Swait(S1,S2,…,Sn)位置 place the process in the waiting queue associated with the first Si found with Si<1,…. endif
Ssignal(S1,S2,…,Sn) for i:=1 to n do Si:=Si+1; # 唤醒所有与si相关的阻塞进程 Remove all the process waiting in the queue associated with Si into the ready queue endfor;
-
信号量集
引入原因:
- 在记录型信号量机制中,wait(S)或signal(S)操作仅能对信号量施以加1或减1操作,意味着每次只能获得或释放一个单位的临界资源。因此,有些进程一次需要N个某类临界资源,此时要进行N次wait(S)操作,显然这是低效的 。
- 在有些情况下,比如系统保留一些特定资源以便系统顺利运行,所以当资源数量低于某一下限值时,不能予以分配。
如何解决:
在AND信号量机制基础上,对Swait和Ssignal操作进行扩充,除了描述当前信号量的参数S 外,增加进程对资源的需求值 d ,以及资源的下限值t 。
Swait(S1,t1,d1,…,Sn,tn,dn) if S1>=t1 and … and Sn>=tn then for i:=1 to n do Si:=Si-di; endfor else # 否则将进程阻塞在第一个不能满足Si<ti资源信号量的队列中并且重新将PC计数器重新指向Swait(S1,t1,d1,…,Sn,tn,dn)位置 Place the executing process in the waiting queue of the first Si with Si<ti. endif
Ssignal(S1,d1,…,Sn,dn) for i:=1 to n do Si:=Si+di; # 唤醒所有与si相关的阻塞进程 Remove all the process waiting in the queue associated with Si into the ready queue endfor;
只有一个信号量S的几种特殊情况:
(1) Swait(S,d,d):它每次申请d个资源,当现有资源数少于d时,不予分配。
(2) Swait(S,1,1):此时的信号量集已蜕化为一般的记录型信号量(S>1时)或互斥信号量(S=1时)。
(3) Swait(S,1,0):一种很特殊且很有用的信号量操作。当S≥1时,允许多个进程进入某特定区;当S变为0后,将阻止任何进程进入特定区,相当于一个可控开关。