:同步与互斥

Posted 快乐江湖

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了:同步与互斥相关的知识,希望对你有一定的参考价值。

费翔林课本习题

思考题

1.试述顺序程序设计的特点以及采用顺序程序设计的优缺点

【答案】

特点:

  • 执行的顺序性:一个程序在处理器上是严格按序执行的,每个操作必须在下一个操作开始前结束
  • 环境的封闭性:运行程序独占全机资源,资源状态只能由此程序本身决定,也不受到外界环境因素影响
  • 结果的确定性:程序在执行过程中允许1出现中断,但是这种中断不会对程序最终结果产生影响,也就是说程序执行结果与他的执行速度无关
  • 过程的可再现性:程序针对同一个数据结构的执行过程在下一次执行时会重现,也即重复执行程序会获得相同搞得执行过程和计算结果

优点是程序的编址和调试很方便,但缺点就是计算机系统效率低下

2.试述并发程序设计的特点以及采用并发程序设计的优缺点

【答案】

特点:程序的执行不再是顺序的,一个程序未执行完而另一个程序便已经开始执行,程序外部的顺序特性消失,程序与计算不再一一对应

优点

  • 若为单处理器系统,可以有效利用资源,让处理器和设备,设备和设备同时工作,充分发挥硬部件的并行工作能力
  • 若为多处理器系统,可以让进程在不同处理器上物理地并行工作,加快计算速度
  • 简化程序设计任务,一般来说,编制并发的小程序进度快,容易保证正确性

缺点

  • 可能会出现各种与时间有关的错误,例如结果唯一或永远等待

【答案】

3.解释并发与并行

【答案】

  • 并行性是指两个或多个事件在同一时刻发生
  • 并发性是指两个或多个事件在同一时间间隔发生

在多道程序环境下,并发性是指在一段时间内宏观上有多个程序在同时运行,但在单处理机系统中,每一时刻却仅能有一道程序执行,故微观上这些程序只能是分时地交替执行

4.解释可再入程序与可再用程序

  • 可再入程序:又称为可重入程序,是指能被多个程序同时调用的程序,是纯代码,在执行过程中不被修改
  • 可再用程序:在调用过程中可以自身修改,在调用它的程序退出之前是不允许其他程序来调用的

5.解释并发进程的无关性和交互性

【答案】

  • 无关性:无关的并发进程是指它们分别在不同的变量集合上操作,一个进程的执行与其他并发进程的进展无关,也即一个进程不会改变另一个与其并发执行进程的变量
  • 交互性:交互的并发进程共享某些变量,一个进程的执行可能会影响其他进程的执行结果,交互的并发进程之间具有制约关系

6.解释进程的竞争与协作关系

【答案】

  • 竞争关系:批处理系统中建立多个批处理进程,分时系统中建立多个交互式进程,它们共享一套计算机系统资源,使得原本不存在逻辑关系的诸进程因共享资源而产生了交互和制约关系,这是间接制约关系,又叫做互斥关系,操作系统必须协调对共享资源的争用
  • 协作关系:一个作业可涉及一组并发进程,它们为了完成共同任务需要分工协作,由于每个进程都独立地以不可预知的速度推进,在执行的先后次序上就要有约束,需要相互协作的进程在某些关键点上协调各自的工作。当其中一个进程到达关键点后,在尚未得到其伙伴进程发来的消息或信号之前应该阻塞自己,等待协作者发来信号或消息后方被唤醒并继续执行。这种协作进程之间需要排定执行先后次序的协调关系是直接制约关系,称为进程同步

7.试述进程的互斥与同步两个概念之间的异同

【答案】

  • 进程同步:进程同步又叫做直接制约关系,它是指为完成某种任务而建立的两个或多个进程,这些进程因为需要在某些位置上协调工作次序而产生一种制约关系
  • 进程互斥:进程互斥叫做间接制约关系,它是指当一个进程访问某临界资源时,另一个想要访问该临界资源的进程必须等待。当前访问临界资源的进程访问结束后,并释放资源后,另一个进程才可以访问

8.什么是临界区和临界资源?临界区管理的基本原则是什么

【答案】

  • 临界区:并发进程中与共享变量有关的程序段称为临界区
  • 临界资源:共享变量所代表的资源称为临界资源

四个原则

  • 空闲让进:临界区空闲时,可以允许一个请求进入临界区的进程立即进入临界区
  • 忙则等待:当已有进程进入临界区时,其他试图进入临界区的进程必须等待
  • 有限等待:对请求访问的进程,应该保证能在有限时间内进入临界区,也就是不能饥饿
  • 让权等待:当进程不能进入临界区时,应该立即释放处理机,防止进程处于忙等待状态

11.试述Deek而算法实现临界区互斥的原理

算法思想:该算法会设置一个布尔型的数组flag[],用于标记各进程是否想要进入临界区,比如"flag[0]=true"表示0号进程 P 0 P_0 P0现在想要进入临界区。每个进程在进入临界区之前先检查当前有没有别的进程想进入临界区,如果没有则把自身对应的标志设置为true,之后开始访问临界区

具体实施:设置一个布尔型的数组flag[],开始时均设置为flase,表示都不想进入临界区,以分析 P 1 P_1 P1为例

  • 开始, P 1 P_1 P1进程会检查 P 0 P_0 P0进程是否想要进入临界区,如果flag[0]=true,那么 P 1 P_1 P1就会被卡住
  • 如果flag[0]=false,表示 P 1 P_1 P1此时确认 P 0 P_0 P0不想进入临界区,那么它就不会被卡住。然后它进入临界区之前,会被自己的flag[1]设置为true,向其他进程表明自己想要进入临界区
  • 临界区访问完毕之后,设置flag[1]=false

算法缺陷:违背了“忙则等待”原则。因为在这种算法下,两个进程是并发的,并发导致异步,意味着两个进程可能会同时访问临界区

10.试述Peterson算法实现临界区互斥的原理

算法思想:为了防止两个进程为了进入临界区而无限期等待,又设置了一个变量turn,每个进程先设置自己的标志后再设置turn标志,再同时检测另一个进程状态标志和不允许进入标志,以保证两个进程同时要求进入临界区时,只允许一个进程进入临界区

具体实施:以分析对于 P 1 P_1 P1进程为例

  • flag[1]=true表示 P 1 P_1 P1想要进入临界区,然后turn=0,是一种“谦让操作”,表示可以优先让 P 0 P_0 P0进入临界区
  • 此时如果 P 0 P_0 P0已经在临界区,那么 P 1 P_1 P1while循环满足,就会被卡住;如果 P 0 P_0 P0不想进入临界区,那么肯定有 P 0 P_0 P0flag[0]=flase, P 1 P_1 P1就不会被卡住

算法优点:遵循了空闲让进、忙则等待、有限等待这三个原则

算法缺陷:相较于前三种算法来说,是比较好的,但是还是有缺陷,未能遵循让权等待的原则。因为在上面的那个例子中,即便 P 1 P_1 P1不能进入临界区,它还是会卡在while循环,不能释放处理机,使处理机处于了忙等状态

11.哪些硬件设施可以实现临界区管理?简述其用法

【答案】


①:中断屏蔽方法
思想:当一个进程正在使用处理机执行它的临界区代码时,为了防止其他进程进入临界区进行访问的,直接“暴力的”禁止一切中断发生,或称之为屏蔽中断、关中断。因为CPU只在发生中断时引起进程切换

优缺点

  • 优点: 简单、高效
  • 缺点: 不适用于多处理机,限制了处理机交替执行程序的能力,因此执行的效率会明显降低;且只适用于内核进程,不适用于用户进程(因为开关中断指令属于特权指令)

②:TestAndSet指令(TSL)
思想:可以为每个临界资源设置一个共享布尔变量locklock=true表示正在被占用,初值设为false。在进程访问临界资源之前,利用TestAndSet检查和修改标志lock,如果有进程在临界区,则重复检查,直到进程退出。大致逻辑如下

while TestAndSet(&lock);//上锁检查
//临界区代码段
lock=false;//解锁、退出区
//剩余区代码段

TestAndSet指令:这是一个原子操作,执行过程中绝对不会被中断,使用硬件实现。其功能是读出指令标志后把该标志设为true。以下是功能描述

bool TestAndSet(bool* lock)

	bool old;//用于存放*lock原来的值
	old=*lock;
	*lock=true;//无论是否加锁,一律设为true
	return old;//返回lock原来的值

具体过程

  • 如果刚开始lock=false,则TSL返回的old就是falsewhile条件不满足,直接进入临界区
  • 如果刚开始lock=true,则TSL返回的old就是true,while条件满足,会一直循环,直到当前访问临界区的进程在退出区进行解锁

优缺点

  • 优点 相比软件方法,TSL把上锁和检查操作使用硬件的方式编程了原子操作。所以实现简单,不会像软件实现那样产生逻辑漏洞
  • 缺点 不满足让权等待 ,暂时无法进入临界区的进程会占用CPU并循环执行TSL,使CPU忙等

③:swap指令(exchange)
能不能完成原子操作可以看其汇编指令,比如++i这就不是原子操作,因为它需要三条汇编指令,需要经过加载-运算-放回操作

思想:可以为每个临界资源设置一个共享布尔变量locklock=true表示正在被占用,初值设为false;然后在每个进程中再设置一个局部变量key,用于和lock交换信息。在进入临界区之前,先利用swap指令交换lockkey的内容,然后检查key的状态,有进程在临界区时,重复交换和检查过程,直到进程退出。大致逻辑如下

key=true;
while(key!=false)
	swap(&lock,&key);
//临界区代码段
lock=false;
//剩余区代码段

swap指令:该指令用于交换两个字的内容,使用硬件实现。属于原子操作,其对应的汇编指令如下

xchgb %al,mutex
  • 王道书上给出了C语言描述,但是我觉得不好,这是原子性操作,那种代码感觉似乎需要三个步骤一样,直接看汇编即可。其中almutex是寄存器

具体过程

  • 如果刚开始临界区就已经被上锁,那么先将其记录在key上,也即key=true,那么此时while循环条件满足,一直执行swap,直到此时处在临界区的进程退出时将lock设为false,交换给key,然后结束循环
  • 如果刚开始临界区没有被上锁,那么先将其记录在key上,也即key=false,那么此时while循环条件不满足,直接进入临界区

优缺点

  • 优点:实现简单,不会像软件实现那样产生逻辑漏洞,适用于多处理机环境
  • 缺点不满足让权等待 ,暂时无法进入临界区的进程会占用CPU并循环执行TSL,使CPU忙等

12.什么是信号量?如何对其分类

【答案】

1965年,荷兰计算机科学家E. W. Djkstra提出新的同步工具一信 号量和PV提作,他将交通管制中多种颜色的信号灯管理方法引人操作系统,让多个进程通过特殊变
量展开交互。一个进程在某一关键点 上被迫停 止执行直至接收到对应的特殊变量值,通过这一措施, 任何复杂的进程交互要求均可得到满足,这种特殊变量就是信号量( semaphore)。为了通过信号量传送信号,进程可利用P和V两个特殊操作来发送和接收信号,如果协作进程的相应信号仍未送到,则进程被挂起直至信号到达为止。在操作系统中用信号量表示物理资源的实体,它是一个与队列有关的整型变量。具体实现时,信号量是一种变量类型,用一个记录型数据结构表示,有两个分量:一个是信号量的值,另一个是信号量队列指针。信号量在操作系统中主要用于封锁临界区、进程同步及维护资源计数。除了赋初值之外,信号量仅能由同步原语PV对其进行操作,不存在其他方法可以检查或操作信号量,PV操作的不可分割性确保执行时的原子性及信号量值的完整性。Dijkstra 发明信号量操作原语:P和V操作(荷兰语中“检测”(Pro-beren)和“增量”( Verhogen)的首字母),常用的符号还有up和down等。利用信号量和PV操作既可解决并发进程竞争问题,又可解决并发进程协作问题

按其用途分类:

  • 公用信号量:联系一组并发进程,相关进程均可在此信号量上执行PV操作,初值为1,用于实现进程互斥
  • 私有信号量:联系一组并发进程,仅允许信号量所用的进程执行P操作,而其他相关进程可在其上执行V操作,初值往往为0或正整数,多用于并发进程同步

按其取值分类:

  • 二值信号量:仅允许取值为0或1,主要用于解决进程互斥问题
  • 一般信号量:允许取大于1的数值,主要用于解决进程同步问题

PV操作

  • P操作(wait(S)原语):这个操作会把信号量减去1,相减后如果信号量<0则表示资源已经被占用,进程需要阻塞;相减后如果信号量 ≥ 0 \\ge0 0,则表明还有资源可以使用,进程可以正常执行
  • V操作(signal(S)原语):这个操作会把信号量加上1,相加后如果信号量 ≤ 0 \\le0 0,则表明当前有阻塞中的进程,于是会把该进程唤醒;相加后如果信号量>0,则表明当前没有阻塞中的进程

13.为什么PV操作均为不可分割的原语操作

【答案】

因为他们被定义为了如下数据结构和不可中断过程(以记录型信号量为例)

typedef struct semaphore

	int value;//信号量值
	struct pcb* list;//信号量队列指针


void P(semapore s)

	s.value--;
	if(s.vaue < 0)
		sleep(s.list);

void V(semaphore s)

	s.value++;
	if(s.value <= 0)
		wakeup(s.list);

14.何为管程?它有哪些属性

【答案】

管程(Monitor):它是一种特殊的软件模块,由以下部分组成

  • 局部于管程的共享数据结构说明——可以理解为类的成员
  • 对该数据结构进行操作的一组过程(函数)——可以理解为类的方法
  • 对局部于管程的数据设置初始值的语句——可以理解为类的构造函数
  • 管程有一个名字——可以理解为类名

所以,管程是一个代表共享资源的数据结构,进程对共享资源的申请、释放等操作是通过过程来实现的(过程就是对这一数据结构的操作),这组过程还可以根据资源情况,或接受或阻塞进程的访问,确保每次仅有一个进程使用共享资源,这样就可以统一管理对共享资源的所有访问,实现进程互斥,即:

monitor Test//定义了一个名称为"Test"的管程

	Data Structure DS;//定义共享数据结构,对应系统中的某种共享资源
	Init_Code()//对共享数据结构初始化语言
	
		DS=5;//初始资源数目为5
	
	
	Take_Away()//过程1:申请一个资源
	
		对共享数据结构的一系列操作
		DS--;//可用资源数目减一
		...
	
	Give_Back()//过程2:归还一个资源
	
		对共享数据结构的一系列操作
		DS++;//可用资源数目加一
		...
	

管程基本特征

  • 共享性:管程中的移出过程可被所有要调用管程的过程的进程所共享
  • 安全性:管程的局部变量只能由此管程的过程访问,不允许进程或其他管程来直接访问,一个管程的过程也不应该访问任何非局部于它的变量
  • 互斥性:在任一时刻,共享资源的进程可以访问管程中的管理此资源的过程,但最多只有一个调用者能够真正进入管程,其他调用者必须等待直至管程可用

15.试述管程中条件变量的含义和作用

【答案】

当一个进程进入管程后被阻塞,直到阻塞的原因解除时,在此期间,如果该进程不释放管程,那么其他进程无法进入管程,为此,将阻塞原因定义为条件变量condition

如果一个进程被阻塞的原因有多个,那么就设置多个条件变量,而每一个条件变量保存了一个等待队列,用于记录因该条件变量而阻塞的所有进程,对于条件变量的操作只有两种:waitsignal

  • x.wait:当x对应的条件不满足时,正在调用管程的进程调用x.wait将自己插入x条件的等待队列,并释放管程。此时其他进程可以使用该管程
  • x.signal:当x对应的条件发生了变化,则调用x.signal,唤醒一个因x条件而阻塞的进程

逻辑描述如下

monitor Test()

	Data Structure DS;//定义共享数据结构,对应系统中的某种共享资源
	condition x;//定义了一个条件变量x
	Init_Code()...
	
	Take_Away()
	
		if(DS<=0)
		
			x.wait();//资源不够,在条件变量x上阻塞的大概
		
		资源足够,分配资源,做一系列相应处理
	
	
	Give_Back()
	
		归还资源,做一系列相应处理
		if(进程在等待)
			x.sginal();//唤醒一个阻塞进程
	

可以看出:相较于信号量,条件变量或者管程把具体的同步互斥关系实现封装了起来,只暴露两个特别简单的接口以供程序员调用,而这两个接口其反应的本质问题就是资源是否存在,能否互斥访问的问题,程序员不用关心复杂的同步互斥关系,只关心在相应的程序逻辑下资源数目的问题

16.试比较管程与进程

【答案】

  • 管程所定义的是公用数据结构,而进程定义的是私有数据结构
  • 管程把共享变量上的同步操作集中在一起统一管理,而临界区却分散在每个进程中
  • 管程是为了解决进程共享资源的互斥而建立的,而进程是为了占有系统资源和实现系统并发性而引入的
  • 管程被欲使用的共享资源的所有进程所调用,管程和调用它的进程不能并行工作;而进程之间可以并行工作
  • 管程可以作为语言或操作系统部分,不必创建或撤销;进程有其生命周期

17.为什么引入进程通信

【答案】

并发进程之间的交互必须满足两个基本要求:同步和通信。进程同步本质上是一
种仅传送信号的进程通信,通过修改信号量,进程之间可以建立联系,相互协调运行和协同工作,但它缺乏传递数据的能力。在多任务系统中,可由多个进程分工协作完成同一任务,于是它们需要共享一些数据和相互交换信息,某些情况下交换的信息量很少,但在很多场合需要交换大批数据,可以通过通信机制来完成。进程之间互相交换信息的工作称为进程通信( Inter - Process Communication,IPC) ,线程通信是从进程通信演变而来,由于可区分单线程结构进程和多线程结构进程,进程通信实质上就是进程中的线程之间的通信。通信方式有很多,包括信号(signal)通信机制,管道( pipeline)通信机

18.试述信件、信箱和间接通信原语

【答案】

19.什么是管道?如何通过管道机制实现进程间通信

【答案】

管道是连接读写进程的一个特殊文件,允许按照FIFO方式传送数据,也能使进程同步执行。管道是单向的,发送进程视管道文件为输出文件,以字符流的形式把大量数据送入管道;接受进程视管道文件为输入文件,从管道中接受数据,所以也称为管道通信

20.试述进程的低级通信工具和高级通信工具

【答案】

21.什么是死锁

【答案】

死锁:所谓死锁,是指多个进程因竞争资源而造成的一种互相等待的局面,若无外力作用,这些进程将无法向前推进

  • 专业定义:如果一个进程集合中的每个进程都在等待只能由此集合中的其他进程才能引发的事件,而无限期陷入僵持的局面称之为死锁

生活中死锁的例子:我拿了你房间的钥匙,而我在自己的房间;你拿了我的房间的钥匙,而你又在自己的房间。如果我要从自己的房间走出去,必须要拿到你手中的钥匙,但是你要走出来又必须要拿到我手中的钥匙,于是形成了死锁

22.试述死锁产生的必要条件

【答案】

①:互斥条件
互斥条件:是指只有对必须互斥使用的资源抢夺时才可能导致死锁。比如打印机设备就可能导致互斥,但是像内存、扬声器则不会

  • 进程A已经获得资源,进程B只能等待

②:不可剥夺条件

不可剥夺条件:是指进程所获得的资源在未使用完之前,不能由其他进程强行夺走,只能主动释放

③:持有并等待条件
持有并等待条件:是指进程已经至少保持了一个资源,但又提出了新的资源请求,但是该资源又被其他进程占有,此时请求进程被阻塞,但是对自己持有的资源保持不放

④:循环等待条件

循环剥夺条件:是指存在一种进程资源的循环等待链,链中的每一个进程已获得的资源同时被下一个进程所请求

23.列举死锁的各种防止策略

【答案】

死锁处理策略:主要分为以下三种

  • 预防死锁:破坏死锁产生的四个必要条件中的一个或几个
  • 避免死锁:用某种方法防止系统进入不安全状态,从而避免死锁。例如银行家算法
  • 死锁的检测和解除:允许死锁产生,不过操作系统会负责检测出死锁的发生,然后采取某种措施解决死锁

应用题

1.如何用信号量实现互斥操作

【答案】

思想:

  • 1:分析并发进程的关键活动,划定临界区
  • 2:设置互斥信号量mutex,初值1
  • 3:在临界区之前执行P操作
  • 3:在临界区之后执行V操作

具体描述:

可用如下描述大致逻辑,有两个进程 P 1 P_1 P1 P 2 P_2 P2

semaphore mutex=1;//互斥信号量
P1()

	//其他代码
	P(mutex);//进入临界区前加锁
	临界区代码
	V(mutex);//退出临界区时要解锁



P1()

	//其他代码
	P(mutex);//进入临界区前加锁
	临界区代码
	V(mutex);//退出临界区时要解锁