lab7中的管程monitor实现有一个信号量next,实际运行时,调用cond_signal函数的进程需要将自己睡眠在next信号量上,等待其他进程从管程中退出或调用cond_wait来唤醒next信号量,才能继续执行。
mooc上的解释是管程中同时只能有一个进程运行,signal函数想要唤醒其他进程就必须让自己进入睡眠。但是信号量的up操作调用的是wakeup_proc来唤醒进程,这只会让proc->state = PROC_RUNNABLE;(见sched.c),也就是说修改相关进程的状态为可运行,等待下一次调度。这也就是说,signal函数在唤醒等待条件变量的进程时并不会马上被调度,而是在下一次时钟中断引发的调度前仍然可以继续执行下面的内容。
按照理论上管程与信号量的实现:
wait(lock){
numWaiting++;
add current thread t to q;
lock.unlock();
schedule();
lock.lock();
}
signal(lock){
if (numWaiting > 0){
remove first thread t from q;
wakeup(t);
numWaiting--;
}
}
假设进程A先调用cond_wait,进程B再调用cond_signal,此时虽然进程B唤醒了进程A,但A仅仅是处于RUNNABLE状态,并没有取得CPU使用权,B仍然可以从容地运行剩余代码。即使因为时钟中断调度到了A,由于此时管程的锁lock仍然被B持有,A的schedule的下一行lock.lock()对应的锁无法获得,依然不会引发互斥访问问题。
综上,monitor中的next信号量似乎没有使用的必要,我猜测其最大的作用也许是为了让等待变量的进程第一时间被唤醒,而非经过一些时间后由正常调度唤醒?还烦请老师解释一下。