信号量(Semaphore)是一个整型变量,可以对其执行 wait 和 signal 操作,也就是常见的 P 和 V 操作。
P、V操作是两条低级进程通信原语。
wait(S)
→ P操作
如果信号量大于 0 ,执行 -1 操作;
如果信号量等于 0,进程睡眠,等待信号量大于 0
signal(S)
→ V操作
对信号量执行 +1 操作,唤醒睡眠的进程让其完成 wait 操作。
P 和 V 操作需要被设计成原语,不可分割,通常可由硬件来实现(中断屏蔽)。
如果信号量的取值只能为 0 或者 1,那么就成为了 互斥量(Mutex) ,0 表示临界区已经加锁,1 表示临界区解锁。
未遵循“让权等待”,使进程处于”忙等“的状态。
不存在“忙等”现象,符合“让权等待”原则。
typedef struct {
int value; // 资源数目
struct process *L; // 链接所有等待该资源的进程
} semaphore;
void wait(semaphore S) {
S.value--;
if (S.value < 0) {
// add this process to S.L;
block(S.L); // 自我阻塞,放弃CPU
}
}
void signal(semaphore S) {
S.value++;
if (S.value <= 0) {
// remove a process P from S.L;
wakeup(P); // 唤醒第一个等待进程P
}
}
PV在不同进程。
typedef int semaphore;
semaphore S = 0;
void P1() {
// do sth.
V(&S); // wake P2
}
void P2() {
P(&S); // wait P1
// do sth.
}