【问题标题】:Why is there a while loop in wait function of a semaphore, when if can be used too?为什么信号量的等待函数中有一个while循环,什么时候也可以使用if?
【发布时间】:2020-12-10 20:49:44
【问题描述】:

这是我的代码:

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

信号量的等待函数中有while循环,不能简单的用if语句吗?

【问题讨论】:

  • if 不是循环语句,只是条件检查
  • if 只检查一次,while 重复检查。
  • 但是为什么要反复检查呢,一次检查不够?

标签: c linux linux-kernel semaphore


【解决方案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
 }

【讨论】:

    【解决方案2】:

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

    我拿了

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

    comment 作为代码的占位符,该代码确实执行了该注释所描述的操作,并且整个代码作为信号量的 实现 的示意图(否则没有信号量可在其中找到,并且 [linux-kernel] 标签也使我朝这个方向倾斜)。在那种情况下...

    考虑两个线程在尝试减少信号量时被阻塞的情况。第三个线程将信号量增加到值 1,导致前两个都解除阻塞。只有一个以前被阻塞的线程可以被允许在那个时候减少信号量,否则它的值将下降到零以下。对方需要检测到它毕竟不能继续,然后回去等待。这就是循环完成的工作。

    【讨论】:

      【解决方案3】:

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

      但是你的代码并没有按照你的想法做。

      while(S == 0) {}
      

      while(S == 0);
      

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

      【讨论】:

      • 我认为 OP 让您感到困惑。在上下文中,他们的代码必须更多地被解释为伪代码,“将线程放入块列表直到它唤醒(通过调用 post)”作为描述真实代码 实际上确实如此,而不仅仅是评论 OP 认为会发生什么。
      • 这是有道理的。我仍然希望第一部分能提供一些价值。
      猜你喜欢
      • 2011-12-07
      • 2011-11-12
      • 2020-12-09
      • 2014-04-05
      • 1970-01-01
      • 1970-01-01
      • 2010-11-11
      • 2020-09-24
      • 1970-01-01
      相关资源
      最近更新 更多