🏷️ 知识点:软件互斥算法
进程P0 和P1的共享变量定义及其初值为
boolean flag[2]; int turn = 0;
flag[ 0 ]=FALSE;
flag[ 1 ]=FALSE;
若进程P0和P1访问临界资源的类C伪代码实现如下:
void PO() {// 进程PO
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时产生的情形是()。
A. 不能保证进程互斥进入临界区,会出现“饥饿”现象 B. 不能保证进程互斥进入临界区,不会出现“饥饿”现象 C. 能保证进程互斥进入临界区,会出现“饥饿”现象 D. 能保证进程互斥进入临界区,不会出现“饥饿”现象
[tag_link]
正确答案:D
这是 Peterson 算法 的实际实现,保证进入临界区的进程合理安全。
该算法为了防止两个进程为进入临界区而无限期等待,设置变量 u,表示不允许进入临界区的编号,每个进程在先设置自己标志后再设置 u 标志,不允许另一个进程进入,这时,再同时检测另一个进程状态标志和不允许进入表示,这样可以保证当两个进程同时要求进入临界区时只允许一个进程进入临界区。
保存的是较晚的一次赋值,因此较晚的进程等待,较早的进程进入。
先到先入,后到等待,从而完成临界区访问的要求。
其实这里可以想象为两个人进门,每个人进门前都会和对方客套一句“你先走”。
如果进门时没别人,就当和空气说句废话,然后大步登门入室;
如果两人同时进门,就互相请先,但各自只客套一次,所以先客套的人请完对方,就等着对方请自己,然后光明正大地进门。
现要求学生使用 swap 指令和布尔型变量 lock 实现临界区互斥。lock 为线程间共享的变量。lock 的值为 TRUE 时线程不能进入临界区,为 FALSE 时线程能够进入临界区。某同学编写的实现临界区互斥的伪代码如题 45(a) 图所示。
(1) 题 45(a) 图中伪代码中哪些语句存在错误?将其改为正确的语句(不增加语句条数)。
(2) 题 45(b) 图中给出了两个变量值的函数 newSwap() 的代码是否可以用函数调用语句“newSwap(&key, &lock)”代替指令“swap key, lock”以实现临界区的互斥?为什么?
[tag_link]
1)进入区中的语句 if (key == TRUE) swap key,lock 存在错误,修改为 while (key ==TRUE) swap key, lock。退出区中的语句 lock=TRUE 存在错误,修改为 lock=FALSE。
2)否。因为多个线程可以并发执行 newSwap(),newSwap() 执行时传递给形参 b 的是共享变量 lock 的地址,在 newSwap() 中对 lock 既有读操作又有写操作,并发执行时不能保证实现两个变量值的原子交换,从而会导致并发执行的线程同时进入临界区。