(1)直接: 相互制约关系源于进程合作,表现为: 进程—进程 (同步:合作完成任务的关系!) 为完成同一个任务的诸进程间,因需要协调它们的工作而相互等待、相互交换信息所产生的直接制约关系。 这种制约主要源于进程间的合作。 发生在相关进程之间 eg:
一次仅允许一个进程使用的共享资源 生产者—消费者问题:
输入指针加1表示为 in:=(in+1)mod n
输出指针加1表示为out:=(out+1)mod n
当out=in时表示缓冲池空
(in+1)mod n=out时表示缓冲池满。
//生产者进程和消费者进程共享的变量:
int n;
typedef struct {……} item;
item buffer[n];
int in, out;
int counter;
//生产者
Producer(){
while(1){
…
produce an item
in nextp;
…
while(counter==n)
do no-op;
buffer[in]=nextp;
in=in+1 mod n;
counter++;
}}
//消费者
Consumer(){
while(1){
while(counter==0)
do no-op;
nextc=buffer[out];
out=out+1 mod n;
counter--;
consume the item
in nextc;
}
}
锁操作原语: 为某临界资源设置一把锁W(布尔量), 设:当W=1时,表示锁是关闭的; 当W=0时,表示锁已打开。
则开锁、关锁原语如下:
//关锁:
Lock(W):
while(W==1);
W=1;
//开锁:
unLock(W):
W=0;
进入区:对欲访问的临界资源进行检查,若此刻未被访问,设正在访问的标志 临界区:访问临界资源 退出区:将正在访问的标志恢复为未被访问的标志 剩余区:其余部分
一、选择题 1. 下列关于临界区和临界资源说法正确的有©。 I.银行家算法可以用来解决临界区(Critical Section)问题。 II.临界区是指进程中用于实现进程互斥的那段代码。 III.公用队列属于临界资源。 IV.私用数据属于临界资源。 A.I、II B. I、IV C.只有III D.都错
2. 我们把在一段时间内,只允许一个进程访问的资源,称为临界资源,因此,我们可以得出下列结论,正确的结论是(D)。 A. 对临界资源是不能实现资源共享的 B. 为临界资源配上相应的设备控制块后,便能被共享 C. 对临界资源应采取同时访问方式,来实现共享 D. 对临界资源,应采取互斥访问方式,来实现共享
3. 一个正在访问临界资源的进程由于申请等待I/O操作而被阻塞时(③) ①可以允许其他进程进入与该进程相关的临界区 ②不允许其他进程进入任何临界区 ③可以允许其他就绪进程抢占处理器,继续运行 ④不允许任何进程抢占处理器
4. 进程间的基本关系为(B)。 A.相互独立与相互制约 B.同步与互斥 C.并行执行与资源共享 D.信息传递与信息缓冲
5. 进程间的同步与互斥,分别表示了各进程间的(D)。 A.相互独立与相互制约 B.动态性与独立性 C.不同状态 D.协调与竞争
6. 若干进程之间相互合作,共同完成一项任务,进程的这种关系称为(D)。 A.互斥 B.并发 C.异步 D.同步
7. 下列哪一种场景问题只包含进程互斥问题?©。 A.两个进程通过一个缓冲区传递数据 B.田径场的四百米接力比赛 C.一个进程读文件,一个进程写文件 D.公共汽车上司机和售票员的工作配合
8. 多个进程并发执行时,各个进程应互斥进入其临界区,所谓临界区是指©。 A.一段数据区 B.一种同步机制 C.一段程序 D.一个缓冲区
9. 由于并发进程执行的随机性,一个进程对另一个进程的影响是不可预测的,甚至造成结果的不正确,(A)。 A.造成不正确的因素与时间有关 B.造成不正确的因素只与进程占用的处理机有关 C.造成不正确的因素只与执行速度有关 D.造成不正确的因素只与外界的影响有关
二、判断题 1. 处于临界区的进程是不可中断的。(×) 解析: 临界区是指访问该临界资源的那段程序代码。 进程互斥是指不允许多个进程同时进入相关临界区,但并没有禁止一个进程对临界资源的访问与另一个进程非临界区代码并发执行, 即:对临界区的执行不是原语。
2. 临界区就是临界资源所在的地址。(×) 解析: 临界区是进程访问临界资源的那段代码。
3. 当两个或多个进程访问同一个临界资源时,每个进程的临界区都是相同的。(×) 解析:
三、简答题 1. 进程的互斥和同步有什么异同点?试举例说明。
可以简单理解为:同步是协作,互斥是竞争
2. 什么叫原语? 答:在操作系统中,往往设计一些完成特定功能的、不可中断的过程,这些不可中断的过程称为原语。
与时间有关的错误 若一种错误的发生与进程的推进速度及外界影响有关,且进程间存在共享变量,则称这种错误为与时间有关的错误。 发生与时间有关的错误的原因: (1) 进程交叉执行。 (2) 涉及公共变量(x)。
1.[2011考研题 32]有两个并发执行的进程P1和P2,共享初值为1的变量x。P1对x加1, P2对x减1。加1和减1操作的指令序列分别如下所示。
//加1操作 //减1操作
load R1,x /*取x到寄存器R1中.*/ load R2, x
inc R1 dec R2
store x,R1 /*将R1的内容存入x*/ store x, R2
两个操作完成后,x的值© A.可能为-1或3 B.只能为1 C.可能为0、1或2 D.可能为-1、0、1或2
解析: 执行①②⑧④⑤⑥结果为1,执行①②④⑤⑥⑧结果为2,执行④⑤①②⑧⑥结果为0,结果-1无法得到。
2. 对下列程序段:
X:=0;Y:=0;
Cobegin
Begin
X:=1; ……①
Y:=Y+X; ……②
End
Coend
当这个程序执行完时,变量X 和Y 的值有可能为: Ⅰ. X=4,Y=2 Ⅱ. X=1,Y=3 Ⅲ. X=4,Y=6 请选出下列答案中唯一正确的一个(D) (A)Ⅰ (B)Ⅰ和Ⅱ ©Ⅱ和Ⅲ (D)Ⅰ、Ⅱ和Ⅲ
3. [2016考研真题30]进程p1和p2均包含并发执行的线程,部分伪代码描述如下所示: 下列选项中, 需要互斥执行的操作是© A.a=1与a=2 B.a=x与b=x C.x+=1 与 x+=2 D.x+=1 与 x+=3 解析:
//进程P1
int x=0;
thread1()
{
int a;
a=1;x+=1;
}
thread2()
{
int a;
a=2;x+=2;
}
//进程P2
int x=0;
thread3()
{
int a;
a=x;x+=3;
}
thread4()
{
int b;
b=x;x+=4;
}
4. 思考题: (1) 进程并发执行一定会导致结果不唯一吗? 答: 进程并发执行可能会导致结果不唯一。 (2) 在什么情况下会顺利执行? 答: 串行访问共享资源。 (3) 在什么情况下可能会出现错误? 答: 同时访问共享资源。
5. 为什么说进程同步问题关系到OS的成败? 答:
设立一个公用整型变量 turn:初值为i;描述允许进入临界区的进程标识;
//进程一
while (turn != i);
critical section
turn = j;
remainder section
//进程二
while (turn != j);
critical section
turn = i;
remainder section
优点: 互斥访问临界资源; 缺点: 强制轮流进入临界区; 违背“空闲让进”原则!
设立一个标志数组flag[]:描述进程是否在临界区,初值均为FALSE。
//进程一
while (flag[j]);
flag[i] = TRUE;
critical section
flag[i] = FALSE;
remainder section
//进程二
while (flag[i]);
flag[j] = TRUE;
critical section
flag[j] = FALSE;
remainder section
优点: 不用交替进入,可连续使用; 缺点: 不能互斥进入,违背“忙则等待”原则
类似于算法2,与算法2的区别在于先修改后检查。可防止两个进程同时进入临界区。
//进程一
flag[i] = TRUE;
while (flag[j]);
critical section
flag[i] = FALSE;
remainder section
//进程二
flag[j] = TRUE;
while (flag[i]);
critical section
flag[j] = FALSE;
remainder section
优点: 可以防止同时进入临界区; 缺点: Pi和Pj可能都进入不了临界区,出现“死等”现象;违背了“有限等待”的原则。
同时使用flag[]和turn; flag标志表示进程是否希望进入临界区或已在临界区,turn用于进程间的互相谦让。
//进程一
flag[i] = true;turn=j;
while (flag[j]&&turn==j);
critical section
flag[i] = false;
remainder section
//进程二
flag[j] = true;turn=i;
while (flag[i]&&turn==i);
critical section
flag[j] = false;
remainder section
1.[2010年考研试题 27]进程 P0 和 P1 的共享变量定义及其初值为: boolean flag[2]; int turn=0; flag[0]=FALSE;flag[1]=FALSE; 若进程 P0 和 P1 访问临界资源的类 C 伪代码实现如下:
void P0() //进程 P0
{
while(TRUE) {
flag[0]=TRUE; turn=1;
while(flag[1]&&(turn==1)) ;
临界区;
flag[0]=FALSE;
}
}
void P1() //进程 P1
{
while(TRUE) {
flag[1]=TRUE; turn=0;
while(flag[0]&&(turn==0)) ;
临界区;
flag[1]=FALSE;
}
}
则并发执行进程 P0 和 P1 时产生的情形是 (D)。 A.不能保证进程互斥进入临界区,会出现“饥饿”现象 B.不能保证进程互斥进入临界区,不会出现“饥饿”现象 C.能保证进程互斥进入临界区,会出现“饥饿”现象 D.能保证进程互斥进入临界区,不会出现“饥饿”现象
2.以下是解决进程互斥进入临界区的一种解法:
P:......
pturn = true;
while (qturn) ;
临界区操作
pturn = false;
......
其中,pturn、qturn的初值为false
Q:......
qturn = true;
while (pturn) ;
临界区操作
qturn = false;
......
如果P、Q两个进程同时想进入临界区,那么会发生下面哪一种情形?(A) A.P和Q都进入不了临界区 B.P和Q都进入了临界区 C.P先进入临界区,Q再进入临界区 D.Q先进入临界区,P再进入临界区
1.关中断 过程:
关中断;
临界区;
开中断;
其余部分;
特点: 简单、高效!
存在问题:
2.专用的机器指令 (1)测试并设置(Test_and_Set)指令
设Lock为全局布尔变量,初值为false;
TS指令定义(逻辑):
Boolean TS(boolean *lock) {
boolean old=*lock;
*lock=true;
return old;
}
使用TS实现互斥:
Do {
While (TS(&Lock));
临界区;
lock=false;
剩余区
}
TS指令的功能是读出指定标志后把该标志设置为真;
(2)对换(Swap)指令
Swap指令定义:
void Swap(boolean *a, boolean *b)
{
boolean temp=*a;
*a = *b;
*b=temp ;
}
3.利用Swap实现进程互斥
key = TRUE;
do{
swap(&lock,&key);
}while(key);
临界区
lock=FALSE;
1.[2016考研题]使用TSL(Test and Set Lock)指令实现进程互斥的伪代码如下所示:
Do{
……
whie(TSL(&lock));
critical section;
lock=FALSE;
……
}while(TRUE);
下列与该实现机制相关的叙述中,正确的是:(B) A.退出临界区的进程负责唤醒阻塞态进程 B.等待进入临界区的进程不会主动放弃CPU C.上述伪代码满足“让权等待”的同步准则 D.whie(TSL(&lock))语句应在关中断状态下执行
4、硬件方法的评价 优点 适用于任意数目的进程; 简单高效且易于证明; 可以使用多个变量支持多个临界区; 缺点 忙等待; 可能饿死; 可能死锁-优先级反转/倒置 ;
**1.**下列哪种方式不支持多处理器环境下的互斥(A)。 A.中断禁用 B.专用机器指令 C.信号量 D.管程
**2.**试分析临界区的大小与系统并发性之间的关系。 答:
**3.**设: CR1是关于一组共享变量SV1的临界区,CR2是关于另一组共享变量SV2的临界区,当进程P1进入CR1时,进程P2是否可以进入CR2? 为什么? 答: 可以。
4.利用锁操作既可以实现进程间的互斥,也能实现进程间的同步,对吗? 答: 错误。
概念: 信号量是一个仅能由原语对其进行操作的整型变量或记录型变量。之所以称其为信号量,来源于交通管理中的信号灯的概念。
信号量又叫信号灯( semaphore ),表示资源的实体,除初值外其值仅能由Wait/Signal (P/V,down/up,sleep/wakeup)原语操作来改变。操作系统利用信号量对进程和资源进行控制和管理。
信号量代表可用资源实体的数量。
信号量
Wait、Signal操作是原语
整型变量; 除初始值外,仅能通过两个原语来访问。
Wait操作 wait(S):
while(S<=0) do no-op;
S=S-1;
Signal操作 signal(S):
S=S+1;
Wait、Signal操作是原子操作,不可中断。 利用信号量实现进程互斥的方法: 为使多个进程互斥的访问某临界资源,须为该资源设置一互斥信号量mutex,并设其初始值为1,然后将各进程访问资源的临界区CS置于wait(mutex)和signal(mutex)之间即可。
semaphore mutex=1;
main(){
cobegin{
process 1: while(1)
{
wait(mutex);
critical section
signal(mutex);
remainder section
}
process 2: while(1)
{
wait(mutex);
critical section
signal(mutex);
remainder section
}
}coend
}
整型信号量未遵循“让权等待”原则,导致“忙等”。 记录型信号量: 一般是由两个成员组成的数据结构,其中一个成员是整型变量,表示该信号量的值,另一个是指向PCB的指针。
记录型信号量: 包含两个数据项,一个是计数值域,另一个是与该信号量对应的进程阻塞队列首指针域。 信号量数据结构的定义:
struct semaphore
{
int value;
PCB *L; //进程队列指针
}
void Wait(struct semaphore s)
{
s.value--;//申请一个单位的资源
if(s.value<0)block(s.L)
//若信号量计数值小于0,
//表示无资源,则阻塞等待,
//重新调度;否则调用进程继续。
}
void Signal(struct semaphore s)
{
s.value++;//释放一个单位的资源
if(s.value<=0)wakeup(s.L)
//若信号量计数值小于等于0
// 表示有进程在等待该资源,
//唤醒一个等待者。
}
信号量的值是与相应资源的使用情况有关的。当它的值大于0时,表示当前可用资源的数量;当它的值小于0时,则其绝对值表示等待使用该资源的进程数,即在该信号量队列上排队的PCB的个数。
利用记录型信号量实现进程互斥
semaphore mutex=1;
main() {
cobegin{
Process 1
while(1){
wait(mutex);
critical section
signal(mutex);
remainder section
}
Process 2
while(1){
wait(mutex);
critical section
signal(mutex);
remainder section
}
}coend
}
互斥信号量的取值范围: 记录型信号量:
整型信号量:
Wait/signal 操作的物理意义 wait操作: 申请一个单位的资源 signal操作:释放一个单位的资源
信号量值>0:表示可用资源的数量; 信号量值<0:其绝对值代表等待使用该资源的进程数。
1. 采用信号量操作管理相关临界区时,若信号量的值可能在[-1,1]之间变化,则与相关临界区有联系的进程个数是(B)。 A 1 B 2 C 3 D 4
2. 用信号量及Wait、Signal操作管理临界区时,若信号量mutex的初值为1,当mutex的等待队列中有k(k > 1)个进程时,信号量的当前值为(A) A. -k B. k-1 C. 1-k D. k
3. n个并发进程通过初值为1的信号量s共享资源R,当n个进程都通过wait(s)申请访问资源R时,信号量s的值为(D)。 A. 0 B. n C. -n D. -(n-1)
4. 与共享资源R相关的信号量s初值为4,经过多次wait和signal操作后s当前值为-2,此时获得R的进程数是(B)。 A. 2 B. 4 C. 0 D. 6
5. 设与某资源R关联的信号量为s,若这个资源最多允许3个进程同时访问,当有5个进程申请访问R时, 采用wait和signal操作来实现同步,则信号量s的取值范围是(C)。 A. 0≤s≤3 B. 0≤s≤5 C. -2≤s≤3 D. 2≤s≤5
6. 在使用信号量及Wait、Signal操作机制解决问题时,进程执行一次Wait操作,意味着该进程(B)。 A.正在使用一个资源 B.申请分配一个资源 C.准备释放一个资源 D.需要共享一个资源
7. 在使用信号量及Wait、Signal操作机制解决问题时,一个进程执行Signal操作意味着( )。 A.该进程从等待队列进入就绪队列 B.可能有另一个进程从等待队列进入就绪队列 C.该进程从磁盘调入内存 D.可能有另一个进程从磁盘被调入内存
8. 当一个进程因在互斥信号量s上执行signal(s)操作而唤醒另一个进程时,则执行signal操作后s的取值范围是(D)。 A. 大于0 B. 大于等于0 C. 小于0 D. 小于等于0
9. 例:多个进程对信号量S进行了5次 wait操作,2次signal操作后,现在信号量的值是 -3,问与信号量S相关的处于阻塞状态的进程有几个?信号量的初值是多少? 答: 解:因为S的当前值是-3,因此与S相关的处于阻塞状态的进程有3个; 设初值为X,因为每进行一次wait(S)操作,S的值都减1,每执行1次signal操作S的值加1,则:X-5+2=-3, X=0
SWait(S1, S2, …, Sn)
if (S1 >=1 && … && Sn>=1)
for( i=1;i<=n;i++)
Si= Si -1 ;
else
Place the process in the waiting queue associated with the first Si found with Si <1,and set the program counter of this process to the beginning of Swait operation
SSignal(S1, S2, …, Sn)
for (i=1;i<=n;i++)
Si= Si +1 ;
Remove all the process waiting in the queue associated with Si into the ready queue
SWait(S1, t1, d1, …, Sn, tn, dn)
if (S1>= t1 && … && Sn>= tn )
for (i=1;i<=n;i++)
Si= Si - di ;
else
Place the executing process in the waiting queue of the first Si with Si < ti and set its program counter to the beginning of the Swait Operation
SSignal(S1, d1, …, Sn, dn)
for( i=1;i<=n;i++)
Si= Si +di ;
Remove all the process waiting in the queue associated with Si into the ready queue
一般信号量集的几种特殊情况
三种信号量的比较 整型信号量->记录型信号量->信号量集机制
信号量的应用 (1) 利用信号量实现互斥
eg:设互斥信号量为mutex (MUTual Exclusion)初值为1。
//进程一
Wait(mutex);
critical section
Signal(mutex);
remainder section
//进程二
Wait(mutex);
critical section
Signal(mutex);
remainder section
说明
(2)用信号量实现简单同步
(3)利用信号量来描述前趋关系 设有两个并发执行的进程P1和P2,P1中有语句S1,P2中有语句S2,希望在S1执行后再执行S2。 需要为进程P2设置一个信号量S,表示前趋是否完成,并赋予其初值为0。
相互合作的进程关系的一种抽象。
若干进程通过有限的共享缓冲区交换数据。其中,"生产者"进程不断写入,而"消费者"进程不断读出;共享缓冲区共有N个;任何时刻只能有一个进程可对共享缓冲区进行操作。
例1:供者和用者通过一个单缓冲区达到同步
解答: 设2个信号量: empty—空缓冲区数(初值为1) full—满缓冲区数(初值为0)
//供者进程
while(1)
{
Wait(empty);
将信息送入缓冲区;
Signal(full);
}
//用者进程
while(1)
{
Wait(full);
从缓冲区取出信息;
Signal(empty);
}
注意: 1.每个进程中用于实现互斥的wait(mutex)和signal(mutex)必须成对地出现。 2.对资源信号量empty和full的wait和signal操作,同样需要成对地出现,但处于不同的进程中。 3.在每个进程中的多个wait操作顺序不能颠倒。应先执行对资源信号量的wait操作,再执行对互斥信号量的wait操作,否则可能引起进程死锁。 4.对同一个信号量的wait与signal可以不在同一个进程中。 5.对任何信号量的wait与signal操作必须配对,同一进程中的多对wait与signal语句只能嵌套不能交叉。
1. 在生产者/消费者问题中,假设有5个生产者,5个消费者共享容量为8的缓冲空间,则实施互斥访问缓冲空间的信号量初始值为(B)。 A. 0 B. 1 C. 5 D. 8
2. 在生产者/消费者问题中,用s表示实施互斥的信号量,e表示与缓冲区空闲空间数量相关的信号量,n表示与缓冲区中数据项个数相关的信号量,下列生产者和消费者的操作(生产者和消费者可并发执行),不可能产生死锁的是(D)。 A.
生产者:
1. wait(s);
2. wait(e);
3. append();
4. signal(n);
5. signal(s);
消费者:
6. wait(s);
7. wait(n);
8. take();
9. signal(e);
10.signal(s);
B.
生产者:
1. wait(s);
2. wait(e);
3. append();
4. signal(n);
5. signal(s);
消费者:
6. wait(n);
7. wait(s);
8. take();
9. signal(s);
10.signal(e);
C.
生产者:
1. wait(e);
2. wait(s);
3. append();
4. signal(s);
5. signal(n);
消费者:
6. wait(s);
7. wait(n);
8. take();
9. signal(e);
10.signal(s);
D.
生产者:
1. wait(e);
2. wait(s);
3. append();
4. signal(s);
5. signal(n);
消费者:
6. wait(n);
7. wait(s);
8. take();
9. signal(s);
10. signal(e);
多个进程共享一个数据区,这些进程分为两组:
读者-写者问题,它为数据库访问建立了一个模型。
为共享数据库设互斥信号量w=1;
void reader(void)
{
while (1) {
……
Wait (w);
读操作
Signal(w);
……
}
}
void writer(void)
{
while (1) {
……
Wait(w);
写操作
Signal(w);
……
}
}
信号量: W = 1 控制互斥访问共享数据对象 R =1 控制读者互斥访问读者计数器 计数器: RC = 0 当前活动的读者数
读者:
……
Wait(R);
if(RC== 0) Wait(W);
RC=RC+1;
Signal(R);
读数据对象;
Wait(R);
RC=RC-1;
If (RC== 0) Signal(W);
Signal(R);
……
写者:
……
Wait(W);
对数据对象写;
Signal(W);
……
int N;
semaphore L=N, w=1;
main(){
cobegin{
reader(){
while(1){
Swait(L, 1, 1);
Swait(w, 1, 0);
...
read;
...
Ssignal(L, 1);
}
}
writer(){
while(1){
Swait(w, 1, 1; L, N, 0);
perform write operation;
Ssignal(w, 1);
}
}
}coend
}
防止写者长期等待 为了读写公平,我们增加一个信号量s,用于在写者进程到达后封锁后续的读者进程。
semaphore s=1;
main()
{
cobegin{
reader{
wait(s);
wait(R);
rc=rc+1;
if(rc==1)wait(W);
signal(R);
signal(s);
reading the file;
wait(R);
rc=rc-1;
if(rc==0)signal(W);
signal(R);
}
writer{
wait(s);
wait(W);
Writing the file;
signal(W);
signal(s);
}
}coend;
}
下面算法即可实现同等优先。 其中信号量W,初值为1,用于写者与其他写者或读者之间的互斥; 另一信号量L,初值为n,表示系统中最多有n个进程可同时进行读操作。
semaphore W=1,L=N;
main(){
cobegin
{
Reader(){
while(1){
wait(W); //是否有写者正在写或请求写操作
wait(L); //读者是否可以读
signal(W); //允许写者申请写的权利
...
perform read operation;
...
signal(L); //出来一个读者
}
}
writer(){
while(1){
wait(W); //申请写操作
for(i=1;i<=n;i++) wait(L); //是否有读者正在读?保证正在工作的读者读完后再执行写操作
perform write operation;
for(i=1;i<=n;i++) signal(L); //恢复L的初值
signal(W); //唤醒被阻塞的读者或写者
}
}coend
}
}
1. 在读者/写者问题中,用R表示读者,W表示写者,下列每个序列从左到右表示进程到达的先后顺序,当采用读者优先方案时,序列(C)可能存在写者饥饿问题。 A. RRRW B. WRRR C. RWRR D. WRRW
五位哲学家围桌而坐 哲学家在思考问题时不需要任何资源,思考完问题后进入进餐态。 每人必须获得左右两支筷子才能进餐。
放在桌子上的筷子是临界资源,在一段时间内只允许一个哲学家使用。为实现对筷子的互斥使用,用一个信号量表示一只筷子,五个信号量构成信号量数组。 semaphore chopstick[5]; 所有信号量均被初始化为1。
死锁解决方法:
第i 位哲学家的活动可描述为:
while(true){
wait(s);
wait(chopstick[ i ]);
wait(chopstick[ ( i +1) %5] );
...
eat;
...
signal(chopstick[ i ]);
signal(chopstick[ ( i +1) % 5] );
signal(s);
...
think;
}
在哲学家进餐问题中,要求每个哲学家先获得两个临界资源(筷子)后方能进餐。本质上是AND同步问题。
semaphore chopstick[5] ={1, 1, 1, 1, 1};
Process i()
{ while(true){
think;
Swait(chopstick[ ( i +1) % 5] , chopstick[ i ] );
eat;
Ssignal(chopstick[ ( i +1) % 5] , chopstick[ i ] );
}
}
第i 位哲学家的活动可描述为:
while(true){
if (i%2!=0) {
wait(chopstick[ i ]);
wait(chopstick[ ( i +1) % 5] ); }
else {
wait(chopstick[( i +1) % 5] );
wait(chopstick[ i]); }
...
eat;
...
signal(chopstick[ i ]);
signal(chopstick[ ( i +1) % 5] );
...
think;
}
}
关于信号量的进一步说明 1. 记录型信号量可以用于两个进程,也可以用于多个进程,既可以用于互斥,也可以用于同步。当互斥与同步共存时,一般来说,用于互斥的信号量上的Wait操作总是在后执行。 2. 用于互斥,常称为互斥(或公用)信号量,其初值为1(临界资源)或n(非临界资源)。
3. 如果用于同步,多采用私用信号量,也称为资源信号量,其初值视资源数而定。它联系一组并发进程,只允许拥有它的进程对其实施Wait操作。 4. 作为资源信号量,当S>0时,其值表示可用资源的数量,执行一次Wait操作意味着请求分配一个单位的资源;若S<=0,表示已无资源,申请资源的进程被阻塞,并排入信号量S的等待队列中,执行一次Signal操作,意味着释放一个单位的资源。
把信号量视为一个加锁标志位,实现对一个临界资源的互斥访问。 实现过程:
Wait(mutex);// mutex的初始值为1
临界区;
Signal(mutex);
非临界区;
把信号量视为是某种类型的共享资源的剩余个数,实现对一类(N个)共享资源的互斥访问。 实现过程:
Wait(R);// R的初始值为该资源的个数N
访问该共享资源;
Signal(R);
其余部分;
把信号量作为进程间的同步工具 。 实现过程:
Wait(s1);
程序段1;
Signal(s2);
Wait(s2);
程序段2;
Signal(s1);