我正在阅读pthread.h;与条件变量相关的函数(如pthread_cond_wait(3))需要一个互斥锁作为参数.为什么?据我所知,我将创建一个互斥锁just作为该参数?那个互斥体应该做什么?

推荐答案

这只是条件变量实现(或最初实现)的方式.

互斥锁用于保护the condition variable itself.这就是为什么你需要在等待前把它锁上.

等待将"自动"解锁互斥锁,允许其他人访问条件变量(用于发送信号).然后,当向条件变量发送信号或广播时,等待列表上的一个或多个线程将被唤醒,该线程的互斥锁将再次被神奇地锁定.

您通常会看到以下带有条件变量的操作,说明它们是如何工作的.下面的示例是一个工作线程,它通过一个条件变量的信号获得工作.

thread:
    initialise.
    lock mutex.
    while thread not told to stop working:
        wait on condvar using mutex.
        if work is available to be done:
            do the work.
    unlock mutex.
    clean up.
    exit thread.

只要等待返回时有一些可用的,工作就在这个循环中完成.当线程被标记为停止工作时(通常由另一个线程设置退出条件,然后启动条件变量以唤醒该线程),循环将退出,互斥锁将解锁,该线程将退出.

上面的代码是单用户模式,因为在工作完成时互斥锁保持锁定.对于多消费者变体,您可以使用example:

thread:
    initialise.
    lock mutex.
    while thread not told to stop working:
        wait on condvar using mutex.
        if work is available to be done:
            copy work to thread local storage.
            unlock mutex.
            do the work.
            lock mutex.
    unlock mutex.
    clean up.
    exit thread.

这允许其他消费者在这个消费者工作的同时接受工作.

condition变量减轻了轮询某个条件的负担,而不是允许另一个线程在需要发生某些事情时通知您.另一个线程可以告诉该线程工作可用,如下所示:

lock mutex.
flag work as available.
signal condition variable.
unlock mutex.

通常被错误地称为虚假唤醒的绝大多数情况通常都是因为多个线程在它们的pthread_cond_wait调用(广播)内收到了信号,其中一个线程将带着互斥体返回,完成工作,然后重新等待.

然后,当没有工作要做时,第二个发出信号的线程可能会出现.因此,您必须有一个额外的变量来指示应该完成的工作(这里的condvar/mutex对本质上是受互斥保护的,但是其他线程需要在更改互斥之前锁定互斥).

从技术上讲,线程从等待状态返回而不被另一个进程踢(这是一个真正的虚假唤醒)是可能的,但是,在我多年从事pthreads的工作中,无论是在代码的开发/服务中,还是作为pthreads的用户,我从来没有收到过其中一个.也许这只是因为惠普有一个像样的实现:-)

在任何情况下,处理错误 case 的代码也会处理真正的虚假唤醒,因为不会为这些事件设置可用工作标志.

C++相关问答推荐

修改pGM使用指针填充2-D数组但不起作用

你能用自己的地址声明一个C指针吗?

字符数组,字符指针,在一种情况下工作,但在另一种情况下不工作?

C指针算法在函数参数中的应用

使用GOTO从多个嵌套循环C继续

Can函数指针指向C++中具有不同参数连续性的函数

带有sigLongjMP中断I/O的异常处理程序

为什么net/if.h在ifaddrs.h之前?

CSAPP微型shell 实验室:卡在sigprocmask

为什么我会收到释放后堆使用错误?

GCC奇怪的行为,有fork 和印花,有换行符和不换行符

当b是无符号字符时,int a=(b<;<;2)>;>;2;和int a=b&;0x3F;之间有什么区别?

Fprintf正在写入多个 struct 成员,并且数据过剩

为什么GCC-O1优化破解了这个代码,为了一个GameBoy高级只读存储器而修改了VRAM的循环?

如何使用WRITE()以指针地址的十六进制形式写入标准输出

按字典顺序打印具有给定字符的所有可能字符串

哪些C++功能可以在外部C块中使用

计算时出现奇怪的计算错误;N Select K;在C中

C 中从 Unix 纪元时间转换的损坏

计算 e^x 很好.但不是 x 的罪