上上篇文章提出了进程件的竞争条件,上一篇文章提出了临界区的概念,通过同一时间只允许一个进程进入临界区的机制从而避免了进程间的竞争条件,本文接上一篇文章主要介绍如何实现同一时间只允许一个进程进入临界区的机制。

方案汇总

  1. 屏蔽中断
  2. 锁变量
  3. 严格轮换法
  4. Peterson解法
  5. TSL指令

一、屏蔽中断

1.1 介绍

在单CPU的系统中可以通过屏蔽中断达到进程间的互斥:当一个进程进入临界区之后马上将系统所有中断屏蔽,等离开临界区域后再打开中断。

当所有屏蔽被屏蔽后,包括时钟中断也会被屏蔽,CPU只有在时钟中断或者其他中断产生的时候才会在各个进程之间进行轮回。SO当中断被屏蔽以后,CPU就不可能让其他进程在运行,当然不会再有其他进程进入临界区域。这是一个简单粗暴的方法来实现目的。且只能通过硬件指令完成。

1.2 缺点

  • 如果让用户进程有屏蔽中断的权力,万一用户进程永远不打开中断怎么办?当然结果就是系统等于down机了
  • 如果系统是多核的,屏蔽中断只影响执行屏蔽中断的CPU,其他CPU照样可以运行其他进程,这个进程有可能就会和其他CPU的进程同时进入临界区域

1.3 优点

  • 实现简单
  • 内核可以用屏蔽中断的方式来实现一些中断操作(但是这个机制用的还是越来越少)

二、锁变量

2.1 描述

锁变量的思想很简单,针对一个临界区域定义一个变量(N)。当一个进程进入这个临界区之前先判断这个N是不是0,如果是0,则也许进入,进入前先把N置为1(这样其他进程就不能进入临界区),离开临界区时再把N置为0(这样其他进程就可以进入临界区)。如下图所示。

ProcessPoolExecutor执行30分钟后卡住_临界区

2.2 缺点

这个方案虽然相对简单,但是有一个致命的缺点,前面的文章里面的Spooler的例子就是个反例。假设Process A先进入了临界区域,再将N修改成1之前,CPU开始了一次切换,Process A停止运行,ProcessB开始运行,这个时候N还是0,所以Process B是可以进入这个临界区的,这样Process A和Process B同时进入了临界区,从而失去了进程间针对临界区域的互斥。所以该方案只是一个尝试,不能从根本上解决问题。

三、严格轮换法

3.1 介绍

严格轮换法同样也是针对一个临界区设置一个变量,假设为Turn。以两个进程为例子:

  • 当Turn为0时,Process 0才能能进入临界区,否则等待。等Process 0离开临界区后,将Turn设置为1.
  • 当Turn为1时,Process 1才能进入临界区,否则等待。等Process 1离开临界区后,将Turn设置为0.

3.2 算法表示

  • 当turn!=0时一直等待
  • turn==0时进入临界区域
  • 离开临界区域后turn设置为1
while(true)
{
     while(turn != 0); //loop
      critical_region();
     turn = 1;
     noncritical_region();
}



  • 当turn!=1时一直等待
  • turn==1时进入临界区域
  • 离开临界区域后turn设置为0
while(true)
{
     while(turn != 1); //loop
      critical_region();
     turn = 0;
     noncritical_region();
}



3.3 缺点

  • 当条件不满足时,进程进入一直循环状态,CPU处于忙等待(Spin Lock),严重浪费CPU资源

下一篇文章介绍改进后的Peterson方案。