信号量机制 - wolai 笔记

1. 整型信号量

  • 用一个整数型变量作为信号量,数值表示某种资源数
  • 整形信号量与普通整型变量的区别:对信号量只能执行 初始化、P、V三种操作
  • 整型信号量存在的问题:不满足让权等待原则
wait(S) {
    while(S <= 0);
    S = S - 1;
}
signal(S) {
    S = S + 1;
}

2. 记录型信号量

  • S.value 表示某种资源数,S.L指向等待该资源的队列
typedef struct {
    int value;
    struct process* L;
}semaphore;
  • P操作中,一定是先 S.value--,进程请求一个单位资源,之后可能需要执行block原语
  • V操作中,一定是先 S.value++,进程是否一个单位资源,之后可能需要执行wakeup原语
  • 注意:要能够自己推断在什么条件下需要执行blockwakeup
  • 可以用记录型信号量实现系统资源的“申请”和“释放”
  • 可以用记录型信号量实现进程互斥、进程同步

3. 实现进程互斥

  • 分析问题,确定临界区
  • 设置互斥信号量,初值为1
  • 临界区之前对信号量执行P操作
  • 临界区之后对信号量执行V操作
semaphore S = 1;  // 初始化同步信号量,初始值为0
P1() {
    P(S);      // 准备开始访问临界资源,加锁
    进程P1的临界区;  
    V(S);      // 访问结束,解锁
}
P2() {
    P(S);      // 准备开始访问临界资源,加锁
    进程P1的临界区;
    V(S);      // 访问结束,解锁
}

4. 实现进程同步

  • 分析问题,找出哪里需要实现“一前一后”的同步关系
  • 设置同步信号量,初始值为0(一般为0,可由用户设定)
  • 在“前操作”之后执行V操作
  • 在“后操作”之前执行P操作
semaphore S = 0;  // 初始化同步信号量,初始值为0
P1() {
    代码1;
    代码2;
    V(S);
    代码3}
P2() {
    P(S);
    代码4;
    代码5;
    代码6}
理解:信号量S代表“某种资源”,刚开始是没有这种资源的。P2需要使用这种资源,而又只能由P1产生这种资源。

5. 实现进程的前驱关系

  • 分析问题,画出前驱图,把每一对前驱关系对看成一个同步问题
  • 为每一对前驱关系设置同步信号量,初始值为0
  • 在每个“前操作”之后执行V操作
  • 在每个“后操作”之前执行P操作

6. 补充

  • P、V操作必须成对出现
  • 缺少P(mutex)就不能保证临界资源的互斥访问
  • 缺少V(mutex会导致资源永不被释放,等待进程永不被唤醒

Comment