2.5 经典进程的同步问题

L10

学习目标

生产者-消费者与哲学家进餐:用信号量/互斥在内核侧协调。验收程序在 user/,机制在 los_sem.c / los_mux.c。

  • 生产者-消费者问题:生产者生产数据放入缓冲区,消费者从缓冲区取数据;需用 wait/signal 操作协调,设置互斥信号量和资源信号量。
  • 哲学家进餐问题:五个哲学家共享五根筷子,需避免死锁和饥饿;统一加锁顺序可预防死锁。
  • 经典同步问题的核心:利用信号量机制解决进程间的制约关系,保证并发执行的正确性。

原理 · 深入理解

生产者 — 有界缓冲 — 消费者 生产者 环形缓冲 N=5 A B 消费者 empty / mutex / full 三个信号量 · 实验 L13 LOS_Sem

2.5 经典进程的同步问题

本节概览:先建立「经典进程的同步问题」的框架,再依次展开下列小节。

  1. 生产者-消费者问题
  2. 哲学家进餐问题
  3. 读者-写者问题

2.5.1 生产者-消费者问题

本节通过三个经典例子阐述进程同步:生产者-消费者、哲学家进餐、读者-写者。

它们分别对应资源争用、循环等待、读写共享三类典型问题,是后续各种同步机制的样板。

  1. 哲学家进餐问题
  2. 读者-写者问题

对于生产者-消费者问题,也可利用AND信号量来解决,即用Swait(empty,mutex)来代替wait(empty)和wait(mutex);用Ssignal(mutex,full)来代替signal(mutex)和signal(full);用Swait(full,mutex)代替wait(full)和wait(mutex),以及用Ssignal(mutex,empty)代替Signal(mutex)和Signal(empty)。

2.利用AND信号量解决生产者-消费者问题。

在利用管程方法来解决生产者-消费者问题时,首先便是为它们建立一个管程,并命名为procducerconsumer,或简称为PC。其中包括两个过程。

  1. put(x)过程
  2. get(x)过程。 对于条件变量notfull和notempty,分别有两个过程cwait和csignal对它们进行操作:

仍存在下述问题。

  1. cwait(condition)过程:当管程被一个进程占用时,其他进程调用该过程时阻塞,并挂在条件condition的队列上
  2. csignal(condition)过程:唤醒在cwait执行后阻塞在条件condition队列上的进程,如果这样的进程不止一个,则选择其中一个实施唤醒操作;如果队列为空,则无操作而返回
  1. PC管程描述如下。

2.5.2 哲学家进餐问题

本节通过三个经典例子阐述进程同步:生产者-消费者、哲学家进餐、读者-写者。

它们分别对应资源争用、循环等待、读写共享三类典型问题,是后续各种同步机制的样板。

  1. 生产者-消费者问题
  2. 读者-写者问题
  1. 上述解法保证不会有两个相邻的哲学家同时进餐,却可能引起死锁。 解决方式:
  2. 仅当哲学家的左右两只筷子均可用时,才允许他拿起筷子进餐
  3. 规定奇数号哲学家先拿他左边的筷子,再拿右边的筷子;偶数号哲学家则相反

至多允许四位哲学家同时去拿左边的筷子,最终能保证至少有一位哲学家能够进餐,并在用毕时能释放出他用过的两只筷子,从而使更多的哲学家能够进餐

利用AND信号量机制解决哲学家进餐问题

在哲学家进餐问题中,要求每个哲学家先获得两个临界资源(筷子)后方能进餐,这在本质上就是前面所介绍的AND同步问题,故用AND信号量机制可获得最简洁的解法。

Semaphore chopstick chopstick[5] = {1,1,1,1,1}; Do{ … //think Sswait(chopstick[(i+1)%5],chopstick[i]); … //eat … Ssignal(chopstick[(i+1)%5],chopstick[i]); }while[TRUE]。

2.5.3 读者-写者问题

本节通过三个经典例子阐述进程同步:生产者-消费者、哲学家进餐、读者-写者。

它们分别对应资源争用、循环等待、读写共享三类典型问题,是后续各种同步机制的样板。

  1. 生产者-消费者问题
  2. 哲学家进餐问题

这里的读者—写者问题增加了一个限制,即最多只允许RN个读者同时读。为此,又引入了一个信号量L,并赋予其初值为RN,通过执行wait(L, 1, 1)操作来控制读者的数目,每当有一个读者进入时,就要先执行wait(L, 1, 1)操作,使L的值减1。

当有RN个读者进入读后,L便减为0,第RN + 1个读者要进入读时,必然会因wait(L, 1, 1)操作失败而阻塞。

2.利用信号量集机制解决读者-写着问题。

做 · 实验

  • 打开工作台 L10,对照 los_mux.c(哲学家)与可选 07-sem(产消)。
  • 烧录 16-classic,A/B 交替 think/eat 且能结束。
  • 选做:烧录 07-sem,串口 P:0 C:0 … 成对出现。
  • 根据「学习目标」列出 3 个关键词,对照原理段落解释给自己听。

打开工作台

经典进程的同步问题

rms-edf

用控件单步操作;日志区记下每一步发生了什么。

代码导读

本课在工作台编译烧录。先读 user 实验入口,再对照 kernel / HDF 中被调用的函数,不要一上来改链接脚本。

总结与提升

  • 无共享缓冲破坏;能对照理论图讲解日志。
  • 能默写产消信号量初值,并能说明本课为何先拿小号叉。
  • 能用自己的话复述学习目标,并指出概念与板上实验的对应。

延伸思考

  • 若两人各先拿自己左边的叉,会怎样?
  • 如果把本节机制拿到 Linux 或完整 OpenHarmony 上,会多出哪些硬件假设?

← 本阶段封面 · 课程列表