二、进程管理(3)同步与互斥

3.1同步与互斥的概念

临界资源与临界区

我们将一次仅允许一个进程使用的资源称为临界资源。许多物理设备都属于临界资源,如打印机等。

在每个进程中,访问临界资源的那段代码称为临界区

同步:亦称直接制约关系,是指为完成某种任务而建立的两个或多个进程,这些进程因为需要协调它们的运行次序而等待、传递信息所产生的制约关系。同步关系源于进程之间的相互合作

互斥:也称间接制约关系。当一个进程进入临界区使用临界资源时,另一个进程必须等待,当占用临界资源的进程退出临界区后,另一进程才允许去访问此临界资源。

为实现对临界资源的互斥访问,应遵循以下准则:

空闲让进。临界区空闲时,可以允许一个请求进入临界区的进程立即进入临界区。

忙则等待。当已有进程进人临界区时,其他试图进入临界区的进程必须等待。

有限等待。对请求访问的进程,应保证能在有限时间内进入临界区,防止进程无限等待。

让权等待(原则上应该遵循,但非必须)。当进程不能进入临界区时,应立即释放处理器,防止进程忙等待。

3.2互斥的基本实现方法

3.2.1软件实现方法

3.2.1.1单标志法

该方法只能实现各个进程轮流访问临界区,但是如果其他进程一直不使用该临界资源的话,要使用临界资源的进程就无法使用临界资源,违反了空闲让进原则

3.2.1.2双标志先检查法

若执行顺序为①⑤②⑥,则P0和P1同时进入临界区,违反了忙则等待原则

3.2.1.3双标志后检查法

若执行顺序为①⑤②⑥,则P0和P1都无法进入临界区,违反了空闲让进有限等待原则

3.2.1.4 Peterson算法

算法思想:当当前进程想使用临界资源时,表达自己要使用资源的意愿,并表示愿意让其他进程先使用,当对方不使用临界资源或者不是自己最后表达了“谦让”的时候,当前进程可以进入临界区

Peterson 算法用软件方法解决了进程互斥问题,遵循了空闲让进、忙则等待、有限等待三个原则,但是当进程无法进入临界区时,进程循环检查是否可以进入临界区,违反了让权等待原则

3.2.2硬件实现方法

3.2.2.1中断屏蔽方法

  • 优点:简单、高效
  • 缺点:不适用于多处理机;只适用于操作系统内核进程,不适用于用户进程(因为开/关中断指令 只能运行在内核态,这组指令如果能让用户随意使用会很危险)

3.2.2.2 TS(TestAndSetLock)指令

  • 优点:实现简单,无需像软件实现方法那样严格检查是否会有逻辑漏洞;适用于多处理机环境
  • 缺点:不满足“让权等待”原则,暂时无法进入临界区的进程会占用CPU并循环执行TSL指令,从而导致“忙等”。

3.2.2.3 Swap指令

逻辑上来看 Swap 和 TSL 并无太大区别,故两者优缺点一样

3.3锁

互斥锁:是一种用于多线程编程中,防止两条线程同时对同一公共资源(比如全局变量)进行读写的机制。

自旋锁:是用于多线程同步互斥的一种锁,线程反复检查锁变量是否可用。由于线程在这一过程中保持执行,因此是一种忙等待。一旦获取了自旋锁,线程会一直保持该锁,直至显式释放自旋锁。如 TSL指令、swap指令、单标志法实现的互斥锁

自旋锁等待期间不用切换进程上下文,多处理器系统中,若上锁的时间短,则等待代价很低;故常用于多处理器系统

3.4信号量

3.4.1记录型信号量

信号量机制是一种功能较强的机制,可用来解决互斥与同步问题,它只能被两个标准的原语wait()和signal()访问,也可简写为P()V()或者简称P操作和V操作

当临界资源被占用时,进程主动阻塞下处理机,遵循让权等待原则

3.4.2信号量机制实现互斥

  1. 分析并发进程的关键活动,划定临界区(临界区代码段一般尽量短)
  2. 设置互斥信号量mutex,初值为1
  3. 在进入区P(mutex)——申请资源
  4. 在退出区V(mutex)——释放资源

3.4.3信号量机制实现同步

  1. 分析什么地方需要实现“同步关系”,即必须保证“一前一后”执行的两个操作
  2. 设置同步信号量S,初始为0
  3. 在“前操作”之后执行V(S)
  4. 在“后操作”之前执行P(S)

3.5管程与条件变量

管程的组成

  1. 管程的名称
  2. 局部于管程内部的共享数据结构说明(定义共享数据结构);
  3. 对局部于管程内部的共享数据设置初始值的语句(给共享数据结构赋值);
  4. 对该数据结构进行操作的一组过程(或函数)

管程的特点

  1. 局部于管程的数据只能被局部于管程的过程所访问;
  2. 一个进程只有通过调用管程内的过程才能进入管程访问共享数据; 
  3. 每次仅允许一个进程在管程内执行某个内部过程。(这种互斥特性是由编译器负责实现)

条件变量

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

通常,一个进程被阻塞的原因可以有多个,因此在管程中设置了多个条件变量。每个条件变量保存了一个等待队列,用于记录因该条件变量而阻塞的所有进程,对条件变量只能进行两种操作,即wait和signal

x.wait当x对应的条件不满足时,正在调用管程的进程调用x.walt将自己插入x条件的等待队列,并释放管程。此时其他进程可以使用该管程。

x.signal:x对应的条件发生了变化,则调用x.signal,唤醒一个因x条件而阻塞的进程。

条件变量和信号量的比较

相似点:条件变量的wait/signal操作类似于信号量的PV操作,可以实现进程的阻塞/唤醒。

不同点条件变量是“没有值”的,仅实现了“排队等待”功能;而信号量是“有值”的,信号量的值反映了剩余资源数,而在管程中,剩余资源数用共享数据结构记录。

3.6经典同步问题

3.6.1生产者-消费者,多生产者-多消费者问题

问题描述

问题分析

  1. 两种进程,生产者进程和消费者进程
  2. 缓冲区属于临界资源,需要互斥访问。
  3. 生产者和消费者之间有同步关系,生产者进程需在缓冲区有空位时才能进行生产,消耗一个缓冲区空位,生产一个产品;相应地,消费者进程需在缓冲区有产品时才能进行消费,消耗一个产品,生产一个缓冲区空位。
  4. 设置信号量,假设初始缓冲区为空,则用mutex=1实现对缓冲区的互斥访问,用empty=n表示空位数,用product=0表示产品数。
  5. 根据分析的同步互斥关系,写出完整过程

死锁分析:如果P(empty)在P(mutex)之后,那么当缓冲区为满时,生产者进程占用了缓冲区却永远无法得到缓冲区空位这个资源(因为缓冲区只能互斥访问,消费者进程无法取出缓冲区的产品),造成死锁。

问题描述

问题分析

如果不使用互斥信号量(mutex),因为盘子空位唯一,当盘子有空位时,父亲进程与母亲进程最多有一个进入临界区,而儿子进程与女儿进程因盘子里无产品,无法进入临界区;同理,盘子不为空时,父亲进程与母亲进程无法进入临界区,而儿子进程与女儿进程只有盘子里有对应产品时才会进去临界区。因此,此情景下,不使用互斥信号量也能实现对临界区的互斥访问

3.6.2读者写者问题(复杂互斥问题)

问题描述

问题分析

  1. 两种进程,读进程写进程
  2. 读进程读数据不会把所读数据从文件中取出,题目并未限定文件写满不能继续写数据(可以继续写并覆盖原有数据),并默认文件起初不为空。因此,读进程和写进程无同步关系。
  3. 同一时间只允许一个写进程进入临界区,故写进程进入临界区前加锁,退出临界区后解锁
  4. 同一时间允许多个读进程进入临界区,故第一个读进程进入临界区时加锁,当所有读进程都退出临界区时解锁。
  5. 进入临界区之前,若临界区有读进程(用count表示临界区的进程数,用一组PV操作实现对count的互斥访问),就跳过P操作,直接进入临界区;退出临界区之前,若临界区有读进程,就跳过V操作,直接离开临界区。
  6. rw实现临界区的互斥访问,用mutex实现对count的互斥访问

在该算法中,如果有源源不断的读进程进入临界区,那么写进程就一直无法进行,造成“饥饿”现象。故增加一个互斥信号量w,实现读写公平策略

读写公平法

在该算法中,当写进程想进入临界区前,会阻塞后续所有读进程进入临界区,只有当写进程出临界区时,后续读进程才能继续进入临界区。拒绝了上一种方法读进程“插队”的现象。

3.6.3哲学家就餐问题

问题描述

问题分析

  1. 一种进程,可以称之为哲学家拿筷子进程
  2. 给n根筷子编号,每根筷子是一种临界资源(每根筷子的位置不同)
  3. 如果所有(n个)哲学家进程并发运行,每个哲学家都拿起左侧的筷子,但拿不到右筷子,就无法进行下去并释放筷子这个临界资源,最终造成死锁
  4. 因此,并发度最高的解法是最多只允许同时n-1个哲学家取筷子,这样至少能保证一个哲学家能顺利就餐并释放筷子
  5. 设置信号量,用chopstick[i]实现对第i根筷子互斥访问,用mutex=n-1保证同时最多有n-1个哲学家取筷子

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值