题目一
如果将 peterson 算法中的 flag[i] = true 与 turn = j 两条语句交换顺序,会导致求解临界区问题所需三个要求(互斥、有空让进、有限等待)中的哪些要求得不到满足?请举例并分析说明得不到满足的情况。
答:
不满足互斥;turn的值决定了哪个进程能允许先进入其临界区;flag表示进程是否想进入临界区;
两条语句交换顺序之后进程Pi和进程Pj的结构分别为上图和下图
- 进程Pi的结构图
do{
turn=j;
flag[i]=true;
while(flag[j]&&turn==j)
临界区
flag[i]=false;
剩余区
}while(true)
- 进程Pj的结构图
do{
turn=i;
flag[j]=true;
while(flag[i]&&turn==i)
临界区
flag[j]=false;
剩余区
}while(true)
两个进程中1234语句的执行顺序共有六种(1必须在2的前面,3必须在4的前面)
turn=j | turn=j | turn=j | turn=i | turn=i | turn=i |
---|---|---|---|---|---|
flag[i]=true | turn=i | turn=i | turn=j | turn=j | flag[j]=true |
turn=i | flag[i]=true | flag[j]=true | flag[i]=true | flag[j]=true | turn=j |
flag[j]=true | flag[j]=true | flag[i]=true | flag[j]=true | flag[i]=true | flag[i]=true |
对于进程 P i P_i Pi而言,不满足turn=j,所以可以进入临界区,而对于进程 P j P_j Pj而言,陷入循环等待,只有当进程 P i P_i Pi从临界区出来时,进程 P j P_j Pj中的flag[i]=false,不满足循环条件, P j P_j Pj进入临界区;此时满足互斥,有空让进,有限等待 | 对于进程 P i P_i Pi而言,不满足turn=j,所以可以进入临界区,而对于进程 P j P_j Pj而言,陷入循环等待,只有当进程 P i P_i Pi从临界区出来时,进程 P j P_j Pj中的flag[i]=false,不满足循环条件, P j P_j Pj进入临界区;此时满足互斥,有空让进,有限等待 | 对于进程 P j P_j Pj而言,不满足flag[i]=true,所以进程 P j P_j Pj进入临界区;对于进程 P i P_i Pi而言,不满足turn=j,故进程 P i P_i Pi也可以进入临界区;所以不满足互斥 | 对于进程 P i P_i Pi而言,不满足flag[j]=true,所以进程 P i P_i Pi可以进入临界区;对于进程 P j P_j Pj而言,不满足turn=i,所以进程 P j P_j Pj可以进入临界区;所以不满足互斥 | 对于进程 P j P_j Pj而言,不满足turn=i,所以进程 P j P_j Pj进入临界区,而对于进程 P i P_i Pi而言,陷入循环等待,只有当进程 P j P_j Pj从临界区出来时,进程 P i P_i Pi中的flag[j]=false,不满足循环条件,进程 P i P_i Pi进入临界区;此时满足互斥,有空让进,有限等待 | 对于进程 P j P_j Pj而言,不满足flag[i]=true,所以进程 P j P_j Pj进入临界区,而对于进程 P i P_i Pi而言,陷入循环等待,只有当进程 P j P_j Pj从临界区出来时,进程 P i P_i Pi中的flag[j]=false,不满足循环条件,进程 P i P_i Pi进入临界区;此时满足互斥,有空让进,有限等待 |
题目二
试分析说明为何自旋锁(spinlocks)不适合单处理器系统但却常用于多处理器系统
答:
- 自旋锁(进程在其等待锁时还在运行)的缺点是忙等待,当一个进程位于其临界区内时,任何其它试图进入其临界区的进程都必须在其进入代码中连续地循环。在单处理器系统中,忙等待浪费了CPU时钟(这些时钟本来可以有效地为其他进程所使用)。
- 自旋锁的优点就是,进程在等待锁时不会进行上下文切换,而上下文切换可能需要花费相当长的时间。因此,如果锁的占用时间短,自旋锁就可以变得非常有用。它常常用于多处理器系统中,这样一个线程在一个处理器自旋时,另一线程可在另一处理器上在其临界区内执行。
题目三
请用比较并交换指令(compare_and_swap())实现互斥锁机制。互斥锁包含的数据结构及函数如下所示,其中 available == 0 表示锁可用,available == 1 表示锁不可用。
typedef struct{
int available;
} lock ;
void acquire (lock *mutex) ;
void release (lock *mutex) ;
答:
在一个进程访问临界区时,其它进程不被允许进入临界区,因此引入了互斥锁机制用于在一个进程访问临界区时进行加锁操作,使得其它进程无法进入临界区,直到当前进程从临界区中返回并释放锁。
compare_and_swap()指令得定义如下:
int CompareAndSwap(int *value, int expected,int new_value)
{
int temp=*value;
if(*value==expected)
*value=new_value;
return temp;
}
用它实现互斥访问
void acquire(lock *mutex){
if(mutex->available){//锁被占用
add this process into waiting queue;//将当前进程加入到等待队列中
block();//阻塞当前进程
}
}
void release(lock *mutex){
CompareAndSwap(mutex->available,1,0);
remove a process P from waiting queue;//将进程P从等待队列中移出
wakeup(P);//唤醒P进程
}
题目四
理发师问题:理发店里有一位理发师、一把理发椅和 n 把供等候理发的顾客坐的椅子。如果没有顾客,理发师便在理发椅上睡觉。当一个顾客到来时,它必须叫醒理发师。如果理发师正在理发时又有顾客到来,如果有空椅子可坐,就坐下来等待,否则就离开。请用信号量机制(wait(),signal())来解决上述问题。
答:
PV操作:对信号量进行相应操作
S:信号量
P(wait()操作):请求操作,相当于S=S-1;S>=0,进程继续进行;否则被挂起
V(signal()操作):释放操作,相当于S=S+1;S>0,进程被唤醒
- 首先定义custNum:当前顾客数量(用于判断后来者是否应该离开),mutex=1:互斥量(保证custNum信号量互斥)
- 确定同步关系:顾客和理发师之间有同步关系,用customer(初值为0)表示顾客是否准备好,用barber(初值为0)来表示理发师是否完成一次理发
- 值得注意的是:并非每个进程都需要while(1)循环,如果顾客剪完一次头发就走了,不可能马上再来剪。