双标志先检查法

【知识回顾】

临界区互斥(软件方法)

基本思想:进程通过while循环判断对方的FLAG是否为true(是true则死循环);若用完临界区后则修改自己的FLAG

典例】假设有2个线程(编号为0和1)需要去访问同一个共享资源,为避免竞争状态的问题,必须实现一种互斥机制,使得在任何时候只能有一个线程访问这个资源,假设有如下一段代码:

Bool flag[2];//flag数组,初始化为FALSE

Enter_Critical_Section(int my_thread_id,int other_thread_id){
    While(flag[other_thread_id]==TRUE);//空循环语句
    Flag[my_thread_id]=TRUE;
}

Exit_Critical_Section(int my_thread_id,int other_thread_id){
    flag[my_thread_id]=FALSE;
}

当一个线程想要访问临界资源,就调用上述的这个两个函数,例如,线程0的代码可能是这样的:

Exit_Critical_Section(0,1); (这里题目的形参只是指0和1线程编号==

使用这个资源;

Exit_Critical_Section(0,1);

做其他的事情;

(1)以上的这种机制能够实现资源互斥访问吗,为什么

【解析】

题目的Enter函数即双标志先检查法

不能。考虑如下情形:

  1. 初始化时,flag数组的2个元素值均为FALSE.
  2. 线程0先执行,执行while循环语句时,由于flag[1]=FALSE,所以顺利结束,不会被卡住。假设这时来了一个时钟中断,打断了它的运行(即0进程未进行enter函数第二句)
  3. 线程1去执行,执行while循环语句时,由于flag[0]为FALSE,所以顺序结束,不会被卡住,然后进入临界区。
  4. 后来当线程0再执行时,也进入临界区,这样就同时有2个线程在临界区。

总结:不能成功的根本原因是无法保证Enter_Critical_Section()函数执行的原子性,我们从上面的软件实现方法中可以看出,对于两个进程间的互斥,最主要的问题是标志的检查和修改不能作为一个整体来执行,因此容易导致无法保证互斥访问的问题。

(2)若把Enter_Critical_Section()函数中的2条语句互换一下位置,结果会如何?

【解析】互换位置后即变成双标志后检查法

可能会出现死锁,考虑如下情形:

  1. 初始化时,flag数组的两个元素值均为FALSE。
  2. 线程0先执行,falg[0]为TRUE,假设这时来了个时钟中断,打断了它的运行
  3. 线程1去执行,flag[1]为TRUE,在执行while循环语句时,由于flag[0]=TRUE,所以在这个地方被卡住,直到时间片用完。
  4. 线程0再执行时,由于flag[1]为TRUE,它也在while循环语句的地方被卡住,因此这两个线程都无法执行下去,从而死锁。

猜你喜欢

转载自blog.csdn.net/qq_35812205/article/details/107733699