有关pthread_cond_wait的原子性操作的问题



众所周知,pthread_cond_wait的调用者将传递锁定到函数的互斥锁,然后以原子方式将调用线程放在等待条件的线程列表中并解锁互斥锁。

我想知道为什么这两个步骤:

  • 将调用线程放在等待条件的线程列表中。
  • 解锁互斥锁

必须是原子的??

如果它们不是原子的,会发生什么?有两种情况:

  • 呼叫步骤 1
  • 呼叫步骤 2

  • 呼叫步骤 2
  • 呼叫步骤 1

等待(或睡眠)和释放互斥锁必须是原子的,以防止睡眠/唤醒竞争。这些是争用条件,其中线程将进入休眠状态,同时另一个线程正在执行某些操作,以使线程不应进入睡眠状态。如果没有一些机制来防止这种类型的比赛,尽管有工作要做,线程仍可能处于睡眠状态 https://www2.cs.duke.edu/courses/spring00/cps110/slides/sleepcv.pdf。

具体来说,原子性保证了在释放互斥锁后发生的pthread_cond_signalpthread_cond_broadcast保证应用等待线程 - 即除非信号唤醒了不同的等待线程,否则它将被唤醒。

重要的是要了解条件变量是无状态的,而不是等待它们的线程列表。如果在没有线程等待的情况下发出条件变量信号,则该信号不执行任何操作。因此,如果首先释放互斥锁,则另一个线程可以获取互斥锁,然后在将等待线程添加到队列之前调用pthread_cond_signal,并且信号将被丢失。之后无法释放互斥锁,因为排队是阻塞操作。(即线程在休眠时无法解锁互斥锁,而睡眠调用是释放互斥锁必须是原子的。

有许多方法可以在内部实现这一点。一种是使用一些条件睡眠机制,例如事件计数器。

最新更新