【问题标题】:POSIX: value of a semaphore after exiting sem_wait()POSIX:退出 sem_wait() 后信号量的值
【发布时间】:2015-07-18 09:11:27
【问题描述】:

信号量被初始化为 0。

sem_t sem;
sem_init(&sem, 0, 0);

一行执行等待信号量,而另一行将其解锁。首先,服务员必须等待的情况。

// value is 0
sem_wait(&sem);  // blocks
                                    // value is 0
                                    sem_post(&sem);
                                    // value becomes 1
// unblocked

第二种,服务员不用等的情况。

                                    // value is 0
                                    sem_post(&sem);
                                    // value becomes 1

// value is 1
sem_wait(&sem);  // does not block
// value has become 0

问题是sem的最终值在两种情况下是不同的:第一种情况下为1,第二种情况下为0。这是一种竞争条件。

在理想情况下,问题不会发生:

  • 当信号量的值为 0 并调用 sem_wait() 时,该值将变为 -1,而不是保持为 0。这样,两种情况下的最终值都将为 0
  • 或存在sem_post() 的变体,它会唤醒一个进程增加值(如果有进程等待,则值不会增加)。同样这样,两种情况下的最终值都是 0

有没有办法解决 POSIX 中的这种差异?

【问题讨论】:

  • 功能不应该是这样的吗,sem_post增加信号量,而sem_wait减少信号量?

标签: c posix semaphore race-condition


【解决方案1】:

我想说你对第一种情况的最终假设是错误的。

从对sem_wait() 的阻塞调用返回时,信号量会递减,因此它的值最终为0

来自man sem_wait()(我的斜体):

sem_wait() 递减(锁定)sem 指向的信号量。如果信号量的值大于零,则递减继续,函数立即返回。如果信号量当前的值为零,则调用阻塞直到可以执行递减(即信号量值上升到零以上),或者信号处理程序中断调用。 p>

上述措辞与wording used by POSIX 不同,但这有助于阐明信号量的“值”如何与信号量锁定状态相关联。

【讨论】:

  • 确实如此。信号量保持内部计数状态,当一个等待线程在发送后准备好时,计数会递减。如果同步对象不以这种方式运行,则它不是信号量。
  • sem_wait()在没有递减信号量的情况下退出时,退出时报错(即等待被信号中断,sem_wait()的返回值为-1,errno为设置为EINTR)。
  • 这就是为什么我们总是测试系统调用的结果,不是吗? ;-) @user377486
猜你喜欢
  • 2016-04-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-04-09
  • 1970-01-01
相关资源
最近更新 更多