并发性:互斥与同步

并发是所有问题的基础,也是操作系统设计的基础。并发包括很多设计问题,其中有进程通信、资源和竞争、多个进程活动的同步以及给进程分配处理器时间等。

感知程度 关系 一个进程对其它进程的影响 潜在的控制问题
进程之间不知道对方的存在 竞争 一个进程的结果与另外一个无关;进程的执行时间可能会受到影响 互斥、死锁、饥饿
进程间接知道对方的存在 通过共享合作 一个进程的结果可能取决于从另一个进程获得的信息;进程的执行时间可能会受到影响 互斥、死锁、饥饿、数据一致性
进程直接知道对方的存在 通过通信合作 一个进程的结果可能取决于从另一个进程获得的信息;进程的执行时间可能会受到影响 死锁(可消耗资源)、饥饿

1. 互斥的要求

  1. 必须强制实施互斥:在与相同资源或共享对象的临界区有关的所有进程中,一次只允许一个进程进入临界区
  2. 一个在非临界区停止的进程不能干涉其他进程
  3. 绝不允许出现需要访问临界区的进程被无限延迟的情况,即不会出现死锁或者饥饿
  4. 对相关进程的执行速度和处理器的数量没有任何要求和限制
  5. 一个进程驻留在临界区中的时间必须是有限的

互斥的硬件支持:

  1. 终端禁用
  2. 专用机器指令

2. 信号量

一般常用的并发机制如下表:

机制 描述
信号量 用于进程间传递信号的一个整数值。在信号量上只能进行三种原子操作(初始化、递减和增加)。递减操作是用于阻塞一个进程,递增操作是用于解除对一个进程的阻塞。信号量也称为计数信号量或一般信号量
二元信号量 只取值0或1的信号量
互斥量 类似于二元信号量。关键区别在于为其加锁(设定值为0)的进程和为其解锁(设定值为1)的进程必须为同一个进程
条件变量 一种数据类型,用于阻塞进程或线程,直到特定的条件为真
管程 一种编程语言结构,它在一个抽象数据类型中封装了变量、访问过程和初始化代码。管程的变量只能由自身的访问过程访问,每次只能有一个进程在其中执行。访问过程即临界区。管程可以有一个进程等待队列
事件标志 用作同步机制的一个内存字。应用程序代码可为标志中的每个位关联不同的事件。通过测试相关的一个或多个位,线程可以等待一个事件或多个事件。在全部所需要的位都被设定或至少有一个位被设定之前,线程会一直被阻塞
消息 两个进程交换信息的一种方法,也可用于同步
自旋锁 一种互斥锁,进程在一个无条件循环中执行,等待锁变量的值可用

2.1 消费者和生产者问题

  1. 有一个或多个生产者生产某种类型的数据,并放置在缓冲区中;
  2. 有一个消费者从缓冲区中取数据,每次取一项;
  3. 系统保证避免对缓冲区的重复操作,即在任何时候只有一个主体(生产者或消费者)可访问缓冲区;
  4. 当缓冲区已满时,生产者不会向其中添加数据;
  5. 当缓冲区为空时,消费者不会从中移走数据。

3. 管程

管程由一个或多个过程、一个初始化序列和局部数据组成的软件模块,其主要特点如下:

  1. 局部数据变量只能被管程的过程访问,任何外部过程都不能访问
  2. 一个进程通过调用管程的一个过程进入管程
  3. 在任何时候,只能有一个进程在管程中执行,调用管程的任何其他进程都被阻塞,以等待管程可用

4. 消息传递

进程交互时,必须满足两个基本要求:同步和通信。为实施互斥,进程需要同步;为实现合作,进程需要交换信息。

两个进程间的通信隐含着某种同步的信息:只有当一个进程发送消息后,接受者才能接收到信息。

消息传递的实际功能通过一对原语实现:

send(destination, message)
receive(source, message)
1
2

寻址 send原语中哪里一个进程接受消息很重要。直接寻址是原语中包括目标进程的识别号。间接寻址时,消息不发送到特定的进程,而是发送到一个共享的数据结构,该结构由临时保存信息的队列组成,这些队列通畅被称为邮箱

5. 读者/写者问题

存在一个多进程共享的数据区,改数据区可以是一个文本或一块内存空间,甚至可以是一组寄存器;有些进程(reader)只能读取这个数据区中的数据,有些进程(writer)只能往数据区中写数据,此外,还必须满足以下条件:

  1. 任意数量的读进程可以同时读取这个文件;
  2. 一次只有一个写进程可以写文件;
  3. 若一个进程正在写文件,则禁止其他任何进程读取文件

5.1 读者优先

第一个试图读的读进程需要等待写进程不再访问共享数据区,当至少一个读进程在读时,随后的读进程无序等待,可以直接进入。

5.2 写者优先

在一个写进程声明想写时,不运行新的读进程进入。

最近更新: 12/9/2018, 10:09:30 PM