c - 这种条件变量的使用是否总是受到丢失信号竞争的影响?

标签 c pthreads posix race-condition condition-variable

假设在信号线程修改影响谓词真值的状态并调用 pthread_cond_signal 而没有持有与条件变量关联的互斥锁的情况下使用条件变量?是否这种类型的使用总是受制于可能会丢失信号的竞争条件?

对我来说,似乎总是存在明显的竞争:

  1. Waiter 将谓词评估为 false,但在它可以开始等待之前...
  2. 另一个线程以一种使谓词为真的方式改变状态。
  3. 另一个线程调用 pthread_cond_signal,它什么也不做,因为还没有等待者。
  4. 等待线程进入 pthread_cond_wait,不知道谓词现在为真,并无限期地等待。

但是,如果情况发生变化,是否总是存在相同类型的竞争条件,以便 (A) 在调用 pthread_cond_signal 时保持互斥量,而不是在更改状态时保持互斥量,或者 (B)以便在更改状态时保留互斥量,而不是在调用 pthread_cond_signal 时保留?

我想知道上述非最佳实践用法是否有任何有效用途,即正确的条件变量实现是否需要考虑此类用法以避免竞争条件本身,或者它是否可以忽略它们,因为它们本来就很活泼。

最佳答案

这里的基本竞赛如下所示:

THREAD A        THREAD B
Mutex lock
Check state
                Change state
                Signal
cvar wait
(never awakens)

如果我们锁定状态变化或信号,或两者,那么我们就避免了这种情况;当线程 A 处于临界区并持有锁时,不可能同时发生状态更改和信号。

如果我们考虑相反的情况,线程 A 交错进入线程 B,则没有问题:

THREAD A        THREAD B
                Change state
Mutex lock
Check state
( no need to wait )
Mutex unlock
                Signal (nobody cares)

因此线程 B 没有特别需要在整个操作期间持有互斥量;它只需要在状态变化和信号之间保持互斥体一段时间,可能是无限小的间隔。当然,如果状态本身需要锁定以进行安全操作,那么也必须在状态更改时保持锁定。

最后,请注意,在大多数情况下,尽早删除互斥量不太可能提高性能。要求持有互斥锁减少了对条件变量中内部锁的争用,并且在现代 pthreads 实现中,系统可以“移动”等待线程从等待 cvar 到等待互斥锁而不唤醒它(从而避免它醒来后立即阻塞在互斥体上)。 正如评论中所指出的那样,在某些情况下,通过减少所需的系统调用数量,删除互斥锁可能会提高性能。然后它也可能导致对条件变量的内部互斥锁的额外争用。很难说。无论如何,这可能都不值得担心。

请注意 applicable standards要求 pthread_cond_signal 无需持有互斥锁即可安全调用:

The pthread_cond_signal() or pthread_cond_broadcast() functions may be called by a thread whether or not it currently owns the mutex that threads calling pthread_cond_wait() or pthread_cond_timedwait() have associated with the condition variable during their waits [...]

这通常意味着条件变量对其内部数据结构有一个内部锁,或者使用一些非常谨慎的无锁算法。

关于c - 这种条件变量的使用是否总是受到丢失信号竞争的影响?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7536057/

相关文章:

c++ - 避免 pthread_cond_wait 和 pthread_cond_signal 时发生死锁

c - 文件内容不会读入结构

C 中的命令行参数

使用 pthread_exit() 返回 retval 时编译警告

posix - 为什么带有 PROT_WRITE 的 mmap(2) 只需要一个可读的 fd?

c++ - 如何包装 posix_memalign(在 mac 上编译旧代码库)?

C pthread_join 段错误

c - 算术表达式作为c中宏的参数

c - 从C中的链表中删除一些元素

c - 练习程序不按预期制造死锁