为什么信号量的wait函数中有一个while循环,什么时候if也可以用?

Why is there a while loop in wait function of a semaphore, when if can be used too?

这是我的代码:

wait(){
    while(S<=0)
       //puts the thread in the block list until it wakes up(by calling post)
    S = S-1
 }

信号量的wait函数中有一个while循环,我不能简单地使用if语句吗?

你这里所说的是主动等待。线程或进程等待变量 S 将其值更改为 1 以访问临界区。一个 IF 只会检查一次然后转到进一步的指令(在这种情况下来自关键部分的指令,这将是一个巨大的错误)。这就是为什么它应该循环等待 - 为了真正等待,而不是只检查一次条件。

但是您的代码并没有像您认为的那样工作。

while(S == 0) {}

while(S == 0);

会完成这项工作。您的代码不断执行 S = S - 1 并根据您的条件创建无限循环。信号量中的 S 永远不应低于 0,因为这意味着一个线程未经许可进入临界区。

Why is there a while loop in wait function of a semaphore, when if can be used too?

我拿

       //puts the thread in the block list until it wakes up(by calling post)

评论作为代码的占位符,代码确实执行评论描述的操作,并且代码总体上是信号量的实现的示意图(否则在其中找不到信号量,[linux-kernel] 标签也让我倾向于这个方向)。那样的话...

考虑两个线程在尝试递减信号量时被阻塞的情况。第三个线程将信号量递增到值 1,导致前两个线程都解除阻塞。只能允许以前阻塞的线程之一在该点减少信号量,否则它的值将降至零以下。另一个需要检测到它毕竟无法继续进行,然后返回等待。这就是循环所完成的。

因为我们不能假设在一个线程被唤醒并且它需要锁之后,另一个线程还没有出现并占用它正在保护的资源:

wait(){ 
    Some  lock_guard(mutex);         // You lock here.

    while(S<=0) {
        condition.wait(lock_guard);  // While you wait here
                                     // the lock is released.
                                     // when the condition/semaphore is signalled
                                     // one or more threads may be released
                                     // but they must aquire the lock before
                                     // they return from wait.
                                     //
                                     // Another thread may enter this function
                                     // aquire the lock and decrement S below
                                     // before the waiting thread aquires the
                                     // lock and thus mustbe resuspended.
    }
    S = S-1
 }