关于信号量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
相关产品推荐
相关产品推荐

