操作系统之进程同步

1. 同步

协调多线程对共享数据的访问,任何时刻只能有一个线程执行临界区代码。

2. 临界区

定义:对共享内存进行访问的程序片段。
实现方法

  • 禁用中断:没有中断,没有上下文切换,因此没有并发。
  • 软件方法:如 Peterson 算法。复杂、需要两个进程间的共享数据项;需要忙等待,浪费 CPU 时间
  • 更高级的抽象方法:硬件提供了一些同步原语,操作系统提供更高级的编程抽象来简化进程同步。如锁。

3. 信号量(semaphore)

信号量是操作系统提供的一种协调共享资源访问的方法,用信号量表示系统资源的数量。

一种抽象的数据类型,由一个整型变量(sem)和两个原子操作组成,操作系统保证 PV 操作的原子性。

  • P()(尝试减少):sem 减 1,如 sem < 0,进入等待,否则继续
  • V()(增加):sem 加 1,如 sem <= 0,唤醒一个等待线程

3.1 信号量实现互斥访问

在这里插入图片描述

3.2 信号量实现同步等待

在这里插入图片描述

3.3 信号量实现生产者消费者问题

问题抽象:

  1. 任何时刻只能有一个线程操作缓冲区(互斥访问)
  2. 缓冲区空时,消费者必须等待生产者(条件同步)
  3. 缓冲区满时,生产者必须等待消费者(条件同步)

用信号量描述每个约束:

  1. 二进制信号量 mutex
  2. 资源信号量 fullBuffers
  3. 资源信号量 emptyBuffers

代码:
在这里插入图片描述

4. 管程

一种用于多线程互斥访问共享资源的程序结构。任意时刻最多只有一个线程执行管程代码,正在管程中的线程可临时放弃管程的互斥访问,等待事件出现时恢复。

组成

  1. 一个锁:控制管程代码的互斥访问;
  2. 0 个或多个条件变量:管理共享数据的并发访问。条件变量是管程内的等待机制,每个条件变量表示一种等待原因,对应一个等待队列。Wait() 操作:将自己阻塞在等待队列中,唤醒一个等待者或释放管程的互斥访问。Signal() 操作:将等待队列中的一个线程唤醒。

管程解决生产者消费者问题
在这里插入图片描述

5. 经典同步问题之哲学家就餐问题

在这里插入图片描述
五个哲学家围着一张圆桌,每个哲学家面前放着食物。哲学家的生活有两种交替活动:吃饭以及思考。当一个哲学家吃饭时,需要先拿起自己左右两边的两根筷子,并且一次只能拿起一根筷子。思考时将两支叉子放回原处。如何保证哲学家们的动作有序进行?不会出现有人永远拿不到叉子。

使用信号量解决:
在这里插入图片描述
根据哲学家不同编号,使其拿起两只筷子的顺序不同,避免五个哲学家都拿到一部分资源构成环路的情况。

6. 读者-写者问题

对共享数据的读写,同一时刻,允许有多个读者同时读;没有读者时写者才能写,没有写着时读者才能读;没有其他写者时才能写。

使用信号量解决:
在这里插入图片描述
读者优先策略:只要有读者正在读状态,后来的读者都能直接进入,如读者持续不断进入,则写者就处于饥饿状态。
在这里插入图片描述
写者优先策略:只要有写者就绪,写者应尽快执行写操作;如写者持续不断进入,则读者就处于饥饿状态。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章