问答题 假设有一个进程拥有两个线程(编号为0和1)需要去访问同一个共享资源,为了避免竞争状态的问题,必须实现一种互斥机制,使得在任何时候只能有一个线程在访问这个资源。假设有如下的一段代码:
int 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的代码可能是这样的:
Enter_Critical_Section(0,1);
……使用这个资源……
Exit_Critical_Section(0,1);
……做其他的事情……
试问:
多选题 该共享资源可以是______。
  • A.进程代码
  • B.线程1的堆栈
  • C.进程所拥有的已打开文件
  • D.计算机全部的地址空间
【正确答案】 A、C
【答案解析】[解析] 线程中的实体基本上不拥有系统资源,只是有一点必不可少的、能保证独立运行的资源,如线程控制块、一些寄存器和堆栈,所以B选项错误。堆栈是线程拥有的资源不可共享。 在同一进程中的各个线程,都可以共享该进程所拥有的资源,但多数情况下,进程只会拥有一定的地址空间,不可能拥有计算机全部的地址空间,所以D选项错误。
问答题 以上的这种机制能够实现资源互斥访问吗?为什么?
【正确答案】这种机制不能实现资源的互斥访问。 考虑如下的情形: 1)初始化的时候,flag数组的两个元素值均为FALSE。 2)线程0先执行,在执行while循环语句的时候,由于flag[1]=FALSE,所以顺利结束,不会被卡住。假设这个时候来了一个时钟中断,则打断它的运行。 3)线程1去执行,在执行while循环语句的时候,由于flag[0]=FALSE,所以顺利结束,不会被卡住,然后就进入了临界区。 4)后来当线程0再执行的时候,也进入了临界区,这样就同时有两个线程在临界区。 不能成功的根本原因是无法保证:Enter_Critical_Section ()函数执行的原子性,从上面的软件实现方法中可以看出,对于两个进程间的互斥,最主要的问题就是标志的检查和修改不能作为一个整体来执行,因此容易导致无法保证互斥访问。
【答案解析】
问答题 如果把Enter_Critical_Section()函数中的两条语句互换一下位置,结果会如何?
【正确答案】可能会出现死锁。 考虑如下的情形: 1)初始化的时候,flag数组的两个元素值均为FALSE。 2)线程0先执行,flag[0]=TRUE,假设这个时候来了一个时钟中断,则打断它的运行。 3)线程1去执行,flag[1]=TRuE,在执行while循环语句的时候,由于flag[0]=TRUE,所以在这个地方被卡住了,直到时间片用完。 4)线程0再执行的时候,由于flag[1]=TRUE,它也在while循环语句的地方被卡住了,这样,这两个线程都无法执行下去,从而死锁。 本题出现死锁的原因是两个线程都可以直接进入Enterl_Critical_Section()函数,并立即对。flag[]进行修改,使flag[0]和flag[1]的值都为TRUE;又因为无法保证:Enter_critical_Section()函数执行的原子性,导致了两个进程在停止while()语句的条件判断上,发生死锁。
【答案解析】