为什么pthread_cond_wait需要锁定?

时间:2013-10-24 09:38:24

标签: c++ linux linux-kernel posix

根据我的理解,pthread_cond_t是一个信号对象,类似于Windows平台上的Event

因此pthread_cond_t的基本功能应该等待它并发出信号。界面应如下:

int pthread_cond_wait(pthread_cond_t* cone);
int pthread_cond_singal(pthread_cond_t* cond);

但实际上,pthread_cond_wait需要一个mutex*类型参数,该参数与其功能没有直接关系。所以你需要一个互斥体,甚至只是想在线程之间创建一个通信信号,而这些信号不能同时访问相同的数据。

那么为什么接口设计如此,并最终给用户增加了开销呢?

EDIT1: 我知道互斥锁用于保护条件数据,但如果设计没有互斥锁的接口,你也可以通过组合互斥锁和pthread_cond来实现你的目标。您还可以使用pthread_cond通知其他线程,这些线程之间没有共享数据。

例如,您可以拥有一个创建文件的生产者线程,在完成后,通知另一个消费者处理文件,没有数据需要被互斥锁保护。

2 个答案:

答案 0 :(得分:4)

条件变量+互斥组合中互斥锁的根本原因是为谓词数据提供保护。

仔细阅读。

条件变量是一种信令机制。 这就是。他们发信号通知 的事情是某些外部谓词条件的预期变化,作为服务员,您订阅了这些条件。当您最终被唤醒您拥有互斥锁时,因此具有对谓词数据的专有权。 这是至关重要的。只要所有需要访问谓词数据的线程按规则播放,并且没有任何线程以任何方式访问中的谓词数据而不拥有底层互斥锁,一切正常。

应用程序开发人员对您来说值得注意的部分同样重要:等待条件变量原子的行为(就您而言,无论如何)开始等待解锁互斥锁以允许其他服务员访问以获取它,从而认可对谓词数据的访问。在Server 2008和Vista之前,通用Windows事件没有这样的东西。我能够描述它在Windows上如何工作的最接近的事情就是解锁hMutex 开始以hEvent原子等待,从而消除潜在的变化潜行这两个行动之间。

这是至关重要的,因为它消除了典型的无保护设置和测试的竞争条件。没有原子解锁和等待的所述竞争条件导致重大问题。例如:您拥有互斥锁,检查数据,而不是您需要的数据,因此您可以解锁互斥锁等待事件。可以想象,在解锁互斥锁并实际开始等待操作之间,您正在等待的条件发生在那段时间内。你错过了它。正确等待cvar-mtx组合时不会发生这种情况。

首先要记住这一点。您可能认为条件变量不会保持“状态”。谓词状态保存在您自己设计的数据变量中。 保护该状态是相关互斥锁的主要工作。您无需拥有谓词数据互斥锁即可发出条件更改信号。但是你需要拥有互斥锁来实际进行更改。如果你不这样做,你就会玩火。


编辑:考虑到现在编辑的问题前提(只有没有共享谓词数据的信号机制),我首先不会使用条件变量+ mutex组合。当需要发送“信号”时,我会使用阻塞管道并向其写入一个字节。并且您无法使用耦合的cvar +互斥体“实体”来设计接口,因为有时您想要更改谓词数据而不向未来的服务员发出信号。你可以只锁定互斥锁并在不调用信号的情况下进行更改。如果他们结合在一起,你就不会有那种奢侈。

答案 1 :(得分:1)

你的前提是不正确的。 不能在没有受互斥锁保护的谓词的情况下使用条件变量。

  

例如,您可以拥有一个创建文件的生产者线程,在完成后,通知另一个消费者处理文件,没有数据需要被互斥锁保护。

所以你建议这样做:

制片:
1.创建文件 2.信号条件变量。

消费者:
1.检查档案 2.如果在场,请停止 3.阻止条件变量。
4.转到步骤1.

那不行。如果消费者完成第2步然后生产者执行第1步和第2步该怎么办?消费者将转到步骤3并等待永远不会发出的信号。信号未被“保存”,因为条件变量是无状态的。您必须自己维护状态,并且由于该状态必须是共享的,因此必须受互斥锁保护。

关于pthread_cond_wait的常见错误信念是它是有条件的等待。它不是。 un 条件等待 条件。