标题基本上说明了一切.如果我使用特定条件和互斥锁调用pthread_cond_wait,那么该线程是否会被阻塞,直到用相应的条件调用pthread_cond_signal?或者无论是否随后再次解锁互斥锁,它都会解锁?
如果答案是前者,我会进行跟进.我有一个队列用于我的线程之间的消息传递.我想确保一次只有一个线程可以将一个项目附加到队列中(因此使用互斥锁).没有任何线程知道是否有任何其他线程将等待自己持有互斥锁.
尝试将项目附加到队列时,我锁定互斥锁,等待队列没有填满pthread条件,然后执行追加,然后解锁互斥锁.在解锁之前,我应该执行pthread_cond_signal,即使我不知道是否还有其他线程在等待?如果多个线程在等待会发生什么?
有人需要发信号/广播条件变量,否则等待线程不一定会被唤醒.你也可以得到"虚假"的唤醒,但不要依赖它们.一旦一个服务员已经被唤醒(通过信号或广播或不合逻辑),它会开始尝试获得互斥体,并且一旦该 pthread_cond_wait回报.
如果有多个线程在等待,则其中一个线程被唤醒(任意或根据实现记录的规则).在您描述的代码中,线程在此condvar上等待的唯一位置是它尝试将项添加到完整队列时.所以你有三个选择:
每次从完整队列中删除元素时都会发出条件变量的信号.这会唤醒0个或更多服务员中的一个.如果队列仍未满,则在添加元素后再次发出信号,以防万一服务员超过1.
每次从完整队列中删除元素时广播条件变量.现在添加元素后无需发出信号.
每次移除元素时都会发出条件变量信号,无论队列是否已满.如果你这样做,不要在以后改变代码的错误,一次删除两个元素,只发信号一次.每次发出信号时,条件变量会将服务员的数量减少一个,这种方法有效,因为它可以防止同时至少有一个服务员,并且尝试获取互斥锁的前服务员比队列中的空格更少.因此,当他们可以使用空间时,你永远不会让线程等待.
想到这一点的方式是,"条件"你等待的是,"队列不完整的".每当状态变成真的,你应该信号或广播的条件变量.如果你选择的信号,并可能有多个服务员,那么每个服务员需要信号(给吵醒旁边的服务员)如果条件保持它完成之后的事情真的.
如果你不关心了一些额外的上下文切换的性能成本,并提供你已经写在condvar等待正确应对虚假尾迹的代码,它也是安全的,当条件是要发出信号或广播condvar还是假的.这是关于条件变量的好东西之一,它使得更容易推断代码的正确性.因此,"只要条件成立,您应该发出信号或广播条件变量"的要求仅表示它所说的内容.当且仅当条件成立时,您不必发出信号.
因此,在这种情况下,每次从队列中删除元素时都会发出信号,无论事先是否已满.在这种情况下很容易的信号的数量减少到最低限度的必要,但有时它是更多的麻烦比它的价值,以制定出确保该条件是否已经成为现实,所以不是你发出信号,如果它现在真实,可能有之前是假的,或者甚至只是发出信号,如果它现在可能是真的.我不建议无缘无故地加入更多的尾声,但有时它会使代码变得更简单.