互斥与同步的解决策略
当前,利用软件方法、硬件方法、信号量方法、管程方法、消息传递方法都可以有效地解决进程间的互斥与同步,其中信号量的方法更具有优势(目前已经通用)。

1. 软件方法:

软件方法是指由进程自己,通过执行相应的程序指令,实现与别的进程的同步与互斥,无须专门的程序设计语言或操作系统的支持。实践证明,该方法很难正确控制进程间的同步与互斥,而且可能会大大地增加系统的额外开销。

软件解决方法有很多种,比较有代表性的软件方法有荷兰数学家Dekker提出的Dekker算法和科学家G.L.Peterson提出的Peterson算法。为了说明设计并发程序时可能出现的典型错误,下面以Dekker算法为例,分析如何设计并改进一个互斥算法的过程。

1.1 初步设想

suppose1:控制两个进程互斥进入临界区,可以让两个进程轮流进入临界区。
suppose2:当一个进程正在临界区执行时,另一个进程就不能进入临界区,而在临界区外等待。
评价
1.该方法可以保证互斥。【相互依赖对方赋予使用的权限】
2.会造成忙等现象,此时互斥的进程并不是处于阻塞状态,而是在不断的循环检测。
3.进程严格交替进入临界区。如果进程需要多次使用临界区,那么使用临界区频率低的进程严重制约着使用临界区使用频率高的进程的执行。【也就是说,如果不交替执行一次,A进程无法持续的推进】
实例
suppose:P0需要每10分钟使用一次临界区,P1需要每1分钟使用一次临界区。
A. 假设turn的初值为0,进程P0正好先请求进入临界区,并成功进入临界区执行,这时,如果P1申请进入临界区,循环检测turn=0,不可以进入,只能“空”循环,等待。
B. 当P0退出临界区时,修改turn的值为1。P1循环检测到turn = 1时,就可以进入临界区执行,退出临界区时,修改turn=0。
C. 根据假设,P1很快又需要进入临界区,但是P0却只能在10分钟之后,按照turn规定的顺序,进入临界区执行,退出时修改turn=1。
即P1必须在临界区空闲的情况下,等待10分钟,才能使用临界区。这不符和互斥原则,降低了系统性能。

1.2 第一次改进

可以为临界区设置一个状态标志,标明临界区是否可用。当临界区空闲时,任何一个进程都能进入,但此时必须修改临界区标志为“被占用”,别的进程就不能进入临界区。当临界区使用完毕,必需修改该标志为“空闲”。
这样就不再使诸进程严格交替使用临界区,而且,如果某进程在临界区外失败,也不会影响其它进程。其算法描述如图所示:
分析:
1. 如果进程在临界区外失败,其他进程不会阻塞。
2. 问题1:“忙等”
3. 问题2:若进程在临界区内失败且相应的flag为true,则其他进程永久阻塞。
4. 问题3:不能保证进程互斥进入临界区。试按以下顺序执行:

1.3 第二次改进

互斥算法的第一次改进不能实现 “互斥” 。因为,进程首先检测临界区状态,若“被占用”,则“忙等”,否则就直接进入临界区。从而,可能出现同时进入临界区的现象。能否让进程预先表明“希望进入临界区的态度”,然后,再检测临界区状态。第二次改进。
分析:
1. 假设P0需要进入临界区,首先执行flag[0]:=true,再执行while flag[1],若P1正在占用临界区,则P0忙等;否则,P0进入临界区。
2. 但是,如果此时P1未占用临界区,而与P0几乎同时需要使用临界区,如下图示:

1.3 第三次改进

互斥算法的第二次改进可能导致死锁,因为P0、P1都“坚持自己的权利,执意进入临界区,且互不谦让”。可以考虑,允许进程既表明需要进入临界区的“态度”,又能相互“谦让”。即首先表示自己需要使用临界区,再检测临界区的状态,若临界区“被占用”,可以等一小段时间再申请。算法如图所示:
分析:
P0、P1的“谦让”可能使它们都不能进入临界区。这种现象不是死锁,因为这种僵局不会是永久行为,某一时刻可能会自动解除。但是,这种现象也是不希望出现的。

1.4 Dekker互斥算法

该算法既允许进程“谦让地”申请进入临界区,又通过给定序号避免“过分谦让”。伪代码描述如下:

1.5 Peterson互斥算法

分析P0的执行:
置flag[0]:=true;{阻止P1进入临界区}
执行while flag[1]
 false, P0进入临界区,执行完成,置
        flag[0]:=false;
 true, P0循环等待,只要P1退出,即可     
         进入

2. 硬件方法:

为了解决软件方法存在的不足,有人提出了硬件解决方法,通过屏蔽中断或采用专门的机器指令控制同步与互斥。与软件解决方法比较,这种方法减少了系统额外开销,但由于需要太强的硬件约束条件,以及可能导致进程饥饿与死锁现象,一直没有成为通用的解决方法。 
采用软件方法实现进程互斥使用临界资源是很困难的,它们通常能实现两个进程的互斥,很难控制多个进程的互斥。算法设计需要非常小心,否则可能出现死锁,或互斥失败等严重问题。软件方法始终不能解决“忙等”现象,降低系统效率。硬件方法包括屏蔽中断和专用机器指令。

2.1 屏蔽中断

由于进程切换需要依赖中断来实现,如果屏蔽中断,则不会出现进程切换。
因此,为了实现对临界资源的互斥使用,可以在进程进入临界区之前,屏蔽中断,当进程退出临界区时,打开系统中断。中断被屏蔽以后,系统时钟中断也被屏蔽。处理机将不会被切换到其他进程。于是,一旦屏蔽中断,进程就可以检查和修改共享内存区中的数据,而不必担心其他进程介入。其伪代码如下:
repeat
<屏蔽中断>;
<临界区>;
<打开中断>;
<其余部分>
forever.
分析:
这种方法约束条件太强,付出的代价太大;因为中断被屏蔽以后,系统将无法响应任何外部请求,也不会响应当前执行进程的任何异常及系统故障,严重地降低了处理机性能。这种方法仅对单处理机系统有效,如果系统有两个或多个共享内存的处理机,屏蔽中断仅仅对执行本指令的处理机有效,其它处理机仍将继续运行,并可以访问共享内存空间。

2.2 专用机器指令

利用一些专用机器指令也能实现互斥,机器指令在一个指令周期内执行,不会受到其它指令的干扰,也不会被中断。Test and Set指令就是较常用的一种机器指令,其定义如下: 
function testset ( var i:integer ) : boolean ;beginif i = 0 thenbegini := 1;testset := true;endelse testset :=false;end.
program mutualexclusion;
const n=…; /*进程数*/
var bolt:integer;
procedure P(i:integer);
beginrepeat
repeat {nothing} until testset (bolt);<临界区>;bolt :=0;<其余部分>forever
end;
begin /* 主程序*/bolt :=0;parbeginP(1);P(2);…P(n)parend
end.

2.3 exchange指令

procedure exchange ( var r :register; var m :memory );
var temp;
begintemp := m;m := r;r := temp;
end.
program mutualexclusion;
const n=…; /*进程数*/
var bolt:integer;
procedure P(i:integer);
var key:integer;
beginrepeatkey:=1;repeat exchange(key,bolt) until key=0;<临界区>;exchange(key,bolt);<其余部分>foreverend;
begin /* 主程序*/bolt :=0;parbeginP(1);P(2);…P(n)parend
end.

2.4 机器指令优点

非常简单,易于证明;同时适合于单处理机系统和共享内存的多处理机系统中多个进程的互斥;可以分别为临界区设置属于它自己的变量,以实现对多个临界区的互斥访问。
“忙等” 现象仍然存在。进程都需要循环检测,等待时机进入临界区。但是,由于采用了机器指令,这种“忙等”消耗的机器时间比软件方法小,属于“可接受的忙等”。可能出现饥饿现象。当临界区空闲时,执行循环检测的若干等待进程能进入临界区的机率是相等的,有的进程可能“运气”非常不好,很难有机会进入临界区,而饥饿。
还有可能导致死锁。
例如,进程P1的优先级低于P2的优先级,若P1通过执行专用机器指令,进入临界区,且在临界区内被中断,P2被调度执行。若P2也需要进入该临界区,由于临界区被P1占用,P2 “忙等” 。由于P1的优先级低于P2,调度程序不可能强行剥夺P2的执行而调度P1。这样,P1将一直占用临界区被中断,P2一直“忙等”,如果没有外力的作用,这种“僵持”状态将一直保持下去,即系统出现死锁。

3.信号量(semaphores)方法

软件方法和硬件方法都存在“忙等”问题,浪费了处理机的时间。信号量方法能实现进程的互斥与同步,而不必“忙等”。(交通信号灯:红灯停,绿灯行就是典型的信号量实例)

3.1 原理

两个或多个进程可以通过传递信号进行合作,可以迫使进程在某个位置暂时停止执行(阻塞等待),直到他收到一个可以“向前推进”的信号(被唤醒)。像影帝,将实现信号灯作用的变量称为信号量,常定义为记录型变量s,其中一个域为整型,另一个域为队列,其元素为等待该信号量的阻塞进程(FIFO)。

3.2 信号量定义及两个原子操作

type semaphore = record
conut:integer;
queue:list of process
end;
var s: semaphore;
========================
wait(s) 和 signal(s)
========================
wait(s)                                                   signal(s)
s.count : = s.count - 1;                           s.count := s.count + 1;
if s.count < 0                                           if s.count <=0
then begin                                              then begin
进程阻塞                                                唤醒队首进程
进程进入s.queue队列;                         将进程从s.queue阻塞队列中移除
end;                                                        end;
进程进入临界区之前,首先执行wait(s)原语,若s.count<0,则进程调用阻塞原语,将自己阻塞,并插入到s.queue 队列中进行排队。
注意,阻塞进程不会占用处理机时间,不是“忙等”。直到某个从临界区退出的进程执行signal(s)原语,唤醒它。
一旦其他某各进程执行了signal(s)原语中的s.count+1操作之后,发现s.count<=0,即阻塞队列中还有被阻塞进程,则调用唤醒原语,把s.queue中第一个进程修改为就绪状态,送就绪队列,准备执行临界区代码。

3.3 利用信号量实现互斥的通用模式

count n=....; //进程数
var s:semaphore(:=1); //定义信号量s,s.count初始化为1
procedure P(i:integer)
begin
repeat
wait(s);//
<临界区>
signal(s);
<其余部分>

forever

end;

begin  //主程序

parbegin

P(1),P(2);......P(n)

parend

end

4.管程方法/*待研究*/

5.消息传递方法/*待研究*/

[OS复习]进程互斥与同步2相关推荐

  1. [OS复习]进程互斥与同步1

    进程互斥与同步 1.引言:多道程序设计存在的问题? 采用多道程序设计技术的操作系统,允许多个进程同时驻留内存并发执行.思考: A.如何协调多个进程对系统资源,如内存空间.外部设备等的竞争和共享? B. ...

  2. 操作系统(二十二)用信号量机制实现进程互斥、同步、前驱关系

    2.3.5 用信号量机制实现进程互斥.同步.前驱关系 目录 2.3.5 用信号量机制实现进程互斥.同步.前驱关系 2.3.5.1 用信号量机制实现进程互斥 2.3.5.2 用信号量机制实现进程同步 2 ...

  3. 用信号量实现进程互斥,同步【操作系统学习笔记】

    21.用信号量实现进程互斥,同步 文章目录 21.用信号量实现进程互斥,同步

  4. 十六、用信号量机制实现进程互斥、同步、前驱关系

    一.知识总览 二.信号量机制实现进程互斥 注意: 1.信号量mutex表示进入临界区的名额 2.对不同的临界资源需要设置不同的互斥信号量 3.P.V操作必须成对出现,缺少P(mutex)就不能保证临界 ...

  5. 二、操作系统——用信号量机制实现进程互斥、同步、前驱关系(详解)

    一.什么是进程同步? 二.什么是进程互斥? 临界资源:一个时间段内只允许一个进程使用的资源 为了实现对临界资源的互斥访问,同时保证系统整体性能,需要遵循以下原则: 空闲让进.临界区空闲时,可以允许一个 ...

  6. (王道408考研操作系统)第二章进程管理-第三节5:用信号量实现进程互斥、同步和前驱关系

    文章目录 一:使用信号量实现进程互斥 二:使用信号量实现进程同步 三:使用信号量实现前驱关系 一:使用信号量实现进程互斥 思想: 1:分析并发进程的关键活动,划定临界区 2:设置互斥信号量mutex, ...

  7. 用信号量实现进程互斥、同步、前驱关系

    信号量机制实现进程互斥 信号量机制实现进程同步 信号量机制实现前驱关系

  8. [OS复习]进程管理5

    线程 1.多线程 操作系统中引入进程的目的: 为了描述和实现多个程序的并发执行,以改善资源利用率及提高系统的吞吐量. 操作系统引入线程的目的: 这是为了减少程序并发执行时系统所付出的额外开销(减少管理 ...

  9. [OS复习]进程管理2

    问题:多个进程竞争内存资源 1.解决方法 方案一:采用交换技术,换出一部分进程到外存,以腾出内存空间 方案二:采用虚拟存储技术,每个进程只能装入一部分程序和数据(存储管理部分) 2.对换技术(交换技术 ...

最新文章

  1. 产品经理如何评估产品机会
  2. Angular——基本使用
  3. c++中类的申明和定义
  4. 转载:ListBox的SelectedValue和SelectedItem的区别
  5. @JVM内存模型(运行时数据区)
  6. Java String substring()方法示例
  7. windows 2003 英文版支持中文显示、中文输入的设置方法
  8. 四叶草默认启动设置方法
  9. 报名 | AI产品经理闭门会_第13期_北京_4场主题分享_本周六(2月19日)
  10. 计算机组成原理期末大纲
  11. 因果推断与反事实预测——利用DML进行价格弹性计算(二十四)
  12. IndentationError: unindent does not match any outer indentation level 错误解决
  13. 语法冠词,虚拟语气,形容词排序
  14. seo如何做外链(做seo外链建设有哪些原则)
  15. Zoreto+坚果云+pdf expert(papership) 实现文献管理和批注同步
  16. 概率论与数理统计大作业实验报告
  17. 微信小程序旋转动画,图片转动view旋转等
  18. 苹果开发者新账号上新app审核被拒绝:Other-Other被拒绝,心路历程记录!
  19. CF677C Vanya and Label
  20. C++函数模板和模板函数、类模板和模板类

热门文章

  1. nagios 监控 mysql 读写比 R/W
  2. SQL JOIN --Merge Join
  3. 时间同步引起的oracle故障二
  4. 二叉苹果树(树型DP+背包)
  5. Web框架 — Flask
  6. 【python】self cls
  7. Nuget包制作最佳解决方案
  8. 117. Populating Next Right Pointers in Each Node II
  9. Spring Boot修改内置Tomcat端口号
  10. 用python爬虫抓站的一些技巧总结