互斥信号量与同步信号量
核心原则:信号量的初值代表其所管理“资源”的初始数量
理解这句话是掌握初值设定的关键。在P、V操作的语境下,一个信号量S
的value
值,代表了当前可用的、由它管理的资源数量。因此,S
的初值就理所当然地代表了在程序开始执行时,该资源的初始可用数量。
为了在考试中快速、准确地确定初值,我们需要将信号量根据其作用进行分类讨论,主要分为两类:互斥信号量和同步信号量。
1. 互斥信号量 (Mutual Exclusion Semaphore)
作用: 用于保护临界区,保证“任一时刻”只有一个进程能进入临界区。
初值设定: 通常恒为 1。
原因 (Why is it 1?):
互斥信号量管理的“资源”是什么?是**“进入临界区的许可”**
-
我们希望在程序一开始时,临界区是空闲的,应该允许一个进程进入。所以,“进入许可”这份资源的初始数量就是1。
-
流程推演:
-
初始时
mutex.value = 1
。 -
第一个进程
P1
到达,执行P(mutex)
。mutex.value
减为0。P1
不阻塞,进入临界区。 -
在
P1
未退出时,第二个进程P2
到达,执行P(mutex)
。mutex.value
减为-1。P2
发现value < 0
,于是阻塞等待。 -
P1
退出临界区,执行V(mutex)
。mutex.value
增加为0。由于value <= 0
,操作系统唤醒等待队列中的P2
。
-
2. 同步信号量 (Synchronization Semaphore)
作用: 用于协调多个进程之间的执行次序,一个进程需要等待另一个进程完成某项任务后才能继续执行(即“前驱关系”)。
初值设定: 根据具体场景的初始资源数决定,通常为 0 或 n。
原因 (Why is it 0 or n?):
同步信号量管理的“资源”是一个事件是否发生、一个条件是否满足、或者某个池子里的产品/空位数。其初值的确定,需要你仔细分析问题的初始状态。
分析方法: 问自己一个问题:“在程序刚开始运行时,消费者/等待者所等待的资源/事件,初始时有多少个?”
经典考题场景分析:
场景一:生产者-消费者问题
-
empty
信号量:-
管理对象: 缓冲区中空闲的位置数量。
-
分析: 生产者进程需要“消费”一个空位置来放产品。在程序开始时,缓冲区是完全空的。
-
初始状态提问: “程序开始时,有多少个空位置可供生产者使用?”
-
答案: 若缓冲区大小为
n
,则有n
个空位置。 -
结论:
semaphore empty = n;
-
-
full
信号量:-
管理对象: 缓冲区中有产品的位置数量(即产品数量)。
-
分析: 消费者进程需要“消费”一个产品。
-
初始状态提问: “程序开始时,缓冲区里有多少个产品可供消费者使用?”
-
答案: 0 个。
-
结论:
semaphore full = 0;
-
总结:一套万能的设定方法
在考场上,当你面对一个信号量大题,按以下步骤思考初值:
-
第一步:识别信号量的作用
-
这个信号量是为了让多个进程不冲突地访问同一个区域吗?
- 是 -> 它是互斥信号量,初值为 1。
-
这个信号量是为了让一个进程等待另一个进程完成某件事吗?
- 是 -> 它是同步信号量,进入第二步。
-
-
第二步:分析同步信号量的初始资源
-
明确该信号量代表的“资源”或“事件”究竟是什么(如:空缓冲区、产品、打印任务完成信号等)。
-
分析整个系统的初始状态(通常是0时刻),判断这个“资源”或“事件”的初始数量是多少。
-
这个数量就是该同步信号量的初值。
-