信号量(Semaphore)是一个整型变量,可以对其执行 wait 和 signal 操作,也就是常见的 P 和 V 操作。

P、V操作是两条低级进程通信原语。

PV操作⭐

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.
}