You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

关于信号量signal()与wait()进程唤醒及执行逻辑的技术疑问

信号量signal()与wait()的定义及疑问解答

一、信号量的两种实现定义

signal()的实现

完整阻塞版本:

signal(semaphore *S) {  
    S->value++;  
    if (S->value <= 0) {  
        // remove a process P from S->list;  
        wakeup(P);  
    }  
}

简化忙等版本:

signal(S) {    
    S++;    
}  

wait()的实现

完整阻塞版本:

wait(semaphore *S) {  
    S->value--;  
    if (S->value < 0) {  
        // add this process to S->list;  
        block();  
    }  
}

简化忙等版本:

wait(S) {  
    while (S <= 0)  
        ; // busy wait  
    S--;  
} 

二、初始场景与操作序列分析

初始场景

Process 90: wait(s1);

Process 91: wait(s1);

Process 95: wait(s1);

此时信号量s1的状态:

semaphore s1 {  
    value = -3;  
    *list = { 90, 91, 95};  // processes will be awakened in order from left to right  
}

操作序列及状态变化(你给出的分析)

Process 101: signal( s1); --> value = -2

Process 81: signal( s1); --> value = -1

Process 100: wait( s1); --> list = {90, 91, 95, 100}

Process 83: signal( s1); --> value = -1

Process 85: signal( s1); --> value = 0

Process 103: signal( s1); --> value = 1, list = {91, 95, 100}

Process 95: signal( s1); --> value = 2, list = {100}

## 三、疑问解答
### 1. 进程95执行signal()时的唤醒逻辑
不会唤醒进程91。根据你给出的**阻塞版signal()定义**,每次调用只会触发最多一次唤醒操作:只有在`S->value++`后,值仍≤0的情况下,才会从队列头部取出一个进程唤醒。

当进程95执行`signal(s1)`时,执行前`s1.value=1`,执行`S->value++`后变为2,2>0,完全不满足唤醒条件,所以不会唤醒任何进程,队列也不会发生变化。

另外补充:哪怕是满足唤醒条件的场景,每次也只会唤醒队列头部的一个进程,被唤醒的进程仅解除阻塞,进入就绪队列等待调度器调度,这个唤醒操作不会改变信号量的`value`——`value`的变化只来自`signal()`里的`S->value++`这一步。

### 2. 进程101执行signal()时的队列变化
不会变成`{101,105}`。进程101是执行`signal()`的进程,它不会进入信号量的等待队列,等待队列里只会存放调用`wait()`后被阻塞的进程。

当进程101执行`signal(s1)`时,初始`s1.value=-3`,执行`S->value++`后变为-2(≤0),此时会从队列头部移除最早进入的进程90并唤醒它,队列会变为`{91,95}`。

内容的提问来源于stack exchange,提问作者HR1596
相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.29 20:55:47