Appearance
408
操作系统
信号量机制
一、定位信息
- 所属圈层:核心层
- 前置知识:了解同步与互斥的基本概念(OS-02-09),了解软件/硬件互斥实现(OS-02-10)
- 知识网络位置:信号量是实现同步与互斥的最核心工具,是经典同步问题(OS-02-12)和管程(OS-02-13)的基础
- 考点热度等级:H级(高频重点)——信号量的操作和应用几乎每年必考,是408操作系统部分的核心考点
二、知识点讲解
2.1 信号量的概念
信号量(Semaphore)是由Dijkstra提出的同步工具,通过两个原子操作 P(wait/申请)和 V(signal/释放)来实现进程间的同步与互斥。
2.2 整型信号量
c
int S; // 信号量,表示资源数量
P(S): // 申请资源
while (S <= 0); // 忙等待
S = S - 1;
V(S): // 释放资源
S = S + 1;问题:不满足"让权等待"(忙等待)。
2.3 记录型信号量(重点)
c
typedef struct {
int value; // 资源数量
struct process *L; // 等待队列
} semaphore;
P(S): // 申请资源
S.value--;
if (S.value < 0) {
// 没有资源了,将当前进程加入等待队列
block(S.L); // 进程阻塞
}
V(S): // 释放资源
S.value++;
if (S.value <= 0) {
// 有进程在等待,唤醒一个
wakeup(S.L); // 从等待队列唤醒一个进程
}关键理解:
S.value > 0:还有可用资源S.value = 0:资源用完,但没有进程在等待S.value < 0:资源用完,且有|S.value|个进程在等待
2.4 信号量实现互斥
c
semaphore mutex = 1; // 互斥信号量,初始值为1
// 进程Pi
P(mutex); // 进入临界区前申请
// 临界区
V(mutex); // 退出临界区后释放2.5 信号量实现同步
c
semaphore S = 0; // 同步信号量,初始值为0
// 进程P1(先执行的操作)
// ...操作A...
V(S); // 通知P2:A已完成
// 进程P2(后执行的操作)
P(S); // 等待P1完成A
// ...操作B...核心思想:P操作"等通知",V操作"发通知"。
2.6 互斥信号量 vs 同步信号量
| 维度 | 互斥信号量 | 同步信号量 |
|---|---|---|
| 初始值 | 1 | 0(通常) |
| 目的 | 保护临界区(互斥) | 协调执行顺序(同步) |
| P/V配对 | 同一进程中P和V配对 | 不同进程中P和V配对 |
| P操作含义 | 申请进入临界区 | 等待前置条件满足 |
| V操作含义 | 释放临界区 | 通知条件已满足 |
三、记忆与理解辅助
- 口诀:"P申请V释放,P等V通知"
- 信号量值的含义:正数=有资源,零=刚好用完,负数=有进程在等待(绝对值=等待进程数)
- 互斥信号量初值=1,同步信号量初值=0——这是最常考的初始值设置
- P/V操作必须成对出现:有P必有V,否则可能导致死锁或永远阻塞
四、例题与精解
例题1(基础巩固)
题目:设信号量S的初始值为3,经过5次P操作和2次V操作后,S的值为( )
A. 0 B. -1 C. 1 D. -2
命题意图:考查信号量值的计算。
精解:
- 审题分析:初始值3,5次P操作(每次-1),2次V操作(每次+1)
- 解题思路:S = 初始值 - P操作次数 + V操作次数
- 完整步骤:
- S = 3 - 5 + 2 = 0
- 但需要注意:当S值降到0以下时,后续P操作会导致进程阻塞
- 前3次P操作:S = 3→2→1→0(进程不阻塞)
- 第4次P操作:S = 0→-1(第4个进程阻塞)
- 第5次P操作:S = -1→-2(第5个进程阻塞)
- 2次V操作:S = -2→-1→0(每次V唤醒一个等待进程)
- 最终S = 0
- 方法反思:S的绝对值在负数时表示等待的进程数。V操作会唤醒等待进程
答案:A
例题2(中等提升)
题目:用信号量实现"进程P1的语句S1执行完后,P2才能执行语句S2"的同步关系,正确的代码是( )
A. 信号量sem=1; P1: S1; V(sem); P2: P(sem); S2; B. 信号量sem=0; P1: S1; V(sem); P2: P(sem); S2; C. 信号量sem=0; P1: P(sem); S1; V(sem); P2: S2; D. 信号量sem=1; P1: P(sem); S1; V(sem); P2: S2;
命题意图:考查信号量实现同步的方法。
精解:
- 审题分析:要求S1先于S2执行,即P2必须等待P1完成S1
- 解题思路:同步信号量初始值为0,P1执行完后V(sem)通知P2,P2先P(sem)等待
- 完整步骤:
- A选项:sem=1时,P2的P(sem)可能在S1执行前就通过了(因为初始值为1,P操作不会阻塞),不满足同步
- B选项:sem=0时,P2的P(sem)会阻塞,直到P1执行S1后V(sem)将其唤醒。正确
- C选项:P1先P(sem)会阻塞(sem=0),导致死锁
- D选项:sem=1时,P1的P(sem)不阻塞直接执行S1,但P2没有P操作,不能保证等待S1完成
- 方法反思:同步信号量初始值=0,"前V后P"——先执行的进程最后V,后执行的进程先P
答案:B
五、考情分析
- 考查频次:近5年每年必考
- 常见题型:选择题 + 综合题(用信号量解决同步问题)
- 分值占比:选择题2分,综合题5–10分
- 命题趋势:信号量的初始值设置、P/V操作的执行结果计算是基础题;用信号量解决经典同步问题是综合题
六、易错点提醒
错误表现:互斥信号量和同步信号量的初始值搞混 错误原因:两者都用信号量,但初始值不同 正确理解:互斥信号量初值=1(表示一个临界区),同步信号量初值=0(表示还没有前置条件)
错误表现:P/V操作不在同一进程中配对 错误原因:将互斥的P/V配对方式套用到同步场景 正确理解:互斥时P/V在同一进程中配对(进入前P,退出后V);同步时P/V在不同进程中(先执行的进程V,后执行的进程P)
错误表现:认为V操作不可能导致进程阻塞 错误原因:只记住了"V释放资源" 正确理解:V操作本身不会阻塞,但V操作后如果有进程被唤醒,当前进程可能被调度器切换(不过这不是V操作导致的阻塞)
错误表现:忘记信号量的P/V操作是原子操作 错误原因:将P/V当作普通函数 正确理解:P和V是原子操作,执行过程中不可被中断
七、来源标注
- 依据2026考研统考408大纲
- 依据《计算机操作系统》(汤小丹/汤子瀛版)第2章
- 依据《操作系统概念》(Silberschatz版)第6章
- 依据王道考研408操作系统辅导讲义