资源互斥访问图例
同步机制应遵循的准则
(1)空闲让进 当无进程处于临界区时,应允许一个请求进入临界区的进程进入临界区;
(2)忙则等待 当已有进程进入临界区时,其他试图进入临界区的进程必须等待;
(3)有限等待 对要求访问临界资源的进程,应保证在有限时间内能进入自己的临界区,以免陷入“死等”状态;
(4)让权等待 当进程不能进入自己的临界区时,应立即释放处理机,以免进程陷入“忙等”。
信号量机制
(1)整型信号量
思想:定义一个整型变量S,除初始化外,仅能通过两个标准的原子操作wait(S)和signal(S)来访问。
wait(S): {while S≤0; /*do no-op*/
S--;
}
signal(S): {
S++;
}
理解:wait过程中,如果不满足则一直在询问,直到满足了才跳出循环,执行后续操作。执行过程中不可中断。不满足中“让权等待”规则。
(2)记录型信号量
思想:用整型变量value代表资源的数目。用进程链表L来链接等待访问临界资源的进程。
记录型信号量的定义:
typedef struct {
int value;
struct process_control_block *list;
}semphore;
wait(semaphare *S)
{
S->value--;
if (S->value<0) block(S->list);
}
signal(semphore *S)
{
S->value++;
if (S->value≤0) then wakeup(S->list);
}
注意:block wakeup 阻塞与唤醒原语
理解:将访问该资源的进程放进等待列表中,使用block原语主动放弃处理机的使用权,当有进程释放资源时,使用wakeup原语将列表中第一个等待的进程唤醒。
(3)AND型信号量
思想:将进程在整个运行过程中需要的所有资源,一次性全部地分配给进程,待进程使用完成后再一起释放。只要尚有一个资源未能分配给进程,其他所有可能为之分配的资源,也不分配给它。亦即,对若干个临界资源的分配,采取原子操作方式:要么全部分配给进程,要么一个也不分配。
AND型信号量的P、V操作
Swait(S1,S2,…,Sn)
{ while (TRUE)
{
if (S1≥1&&… &&Sn≥1){
for (i=1;i<=n;i++) Si--;
break;
}
else {将进程放入第一个Si
(4)信号量集
思想:若进程一次需要申请多类临界资源,则在进行临界资源分配时,先测试各类临界资源是否大于其下限值。若低于下限值,则不予分配。
信号量集的P、V操作
Swait(S1,t1,d1,…,Sn,tn,dn)
while (TRUE){
if (S1≥t1 && … && Sn≥tn )
for (i=1;i<=n;i++) Si:=Si-di;
break;
}
else { Place the executing process in the waiting queue of the first Si with Si
四种信号量的比较
(4)信号量集:可申请n类资源,每类资源有m个,每次可申请每类资源中的多个。但低于下限时,不予分配
利用信号量实现前趋关系
方法:
(1)前趋图有几条边则初始几个信号量
(2)如果有边到达结点,则wait()
(3)如果有边从结点出发则signal()
事例:
P1() {S1;signal(a);signal(b);}
P2(){wait(a);S2;signal(c);signal(d);}
p3(){wait(c);S3;signal(e);}
P4(){wait(d);S4;signal(f);}
P5(){wait(b);S5;signal(g); }
P6(){wait(e);wait(f);wait(g);S6;}
Main(){
Semaphore a,b,c,d,e,f,g;
a.value=b.value=c.value=0;
d.value=e.value=0;
f.value=g.value=0;
cobegin
P1();p2();p3();p4();p5();p6();
coend}
进程同步问题
(1)生产者与消费者问题
Int in=0;out=0;
Item buffer[n];
Semaphore mutex=1,empty=n,full=0;
void procedure() {
do{
produce an item in nextp;
…
wait(empty);
wait(mutex);
buffer(in)=nextp;
in=(in+1%n;
signal(mutex);
signal(full);
}while(TRUE);
}
Void consumer(){
do{
wait(full);
wait(mutex);
nextc=buffer(out);
out=(out+1)%n;
signal(mutex);
signal(empty);
consumer the item in nextc;
…
}while (TRUE);
}
Void main() {
Cobegin
procedure();consumer();
coend;
}
理解:
(1)生产者:
(1)查看产品是否满,满了则等待消费者来拿不生产,不满继续判断
(2)看看是否有人在,有人在则不生产,等待出来
(3)生产过程
(4)退出操作室
(5)通知可以进来取商品了
(2)消费者
(1)查看产品是否为空 ,空了则等待生产者来生产。不为空则继续判断
(2)查看是否有人在,有人在则不取产品,等待出来
(3)取产品过程
(4)退出操作室
(5)通知可以进来生产了
(3)互斥信号量的PV操作在同一段程序中,资源信号量的PV操作分别处于不同程序中
(4)资源信号量与互斥信号量wait的顺序不能更改
若更改,可能引发进程死锁
更改后分析过程:
生产者
(1)判断是否有人在,没人进去
(2)判断是否满,满了,等待消费者来拿
消费者
(1)判断是否有人,--- 有人 --- 等待
生产者不出去消费者没法进来,消费者不拿走产品,生产者无法生产,无法生产无法出去,无法出去消费者无法进来。
死锁