pthread_cond_wait与信号量
使用pthread_cond_wait
或使用信号量的优点/缺点是什么? 我正在等待这样的状态变化:
pthread_mutex_lock(&cam->video_lock); while(cam->status == WAIT_DISPLAY) { pthread_cond_wait(&cam->video_cond, &cam->video_lock); } pthread_mutex_unlock(&cam->video_lock);
使用正确初始化的信号量,我想我可以这样做:
while(cam->status == WAIT_DISPLAY) { sem_wait(&some_semaphore); }
每种方法的优缺点是什么?
信号量适合生产者 – 消费者模型,尽pipe它还有其他用途。 你的程序逻辑负责确保等待的次数是正确的。 如果你发布一个信号而没有人在等待,那么当他们等待时,他们立即继续。 如果你的问题是可以用信号量的计数值来解释的话,那么应该很容易用信号量来解决。
条件variables在某些方面有点宽容。 例如,你可以使用cond_broadcast来唤醒所有的服务员,生产者不知道有多less。 如果你没有任何人在等待它,那么没有任何反应。 如果你不知道是否会有兴趣的听众,这是很好的。 这也是为什么聆听者应该总是在等待之前检查互斥状态 – 如果他们不这样,他们可能会错过一个信号,直到下一个(永远不会)才会醒来。
所以一个条件variables适合于通知有关方状态已经改变:你获得互斥量,改变状态,信号(或广播)condvar并释放互斥量。 如果这描述你的问题,你在condvar领土。 如果不同的听众对不同的状态感兴趣,可以直接播放,然后每个人都会醒来,找出他们是否已经find自己想要的状态,如果不再等待。
用互斥量和信号量来尝试这样的事情确实非常难以理解。 问题出现的时候,你想要采取互斥,检查一些状态,然后等待信号的变化。 除非你能自动释放互斥体并等待信号量(在线程中你不能),否则你最终等待信号量,同时持有互斥量。 这会阻止互斥体,也就是说别人不能把它做成你所关心的改变。 所以你会被诱惑添加另一个互斥体的方式,这取决于你的具体要求。 也许是另一个信号量。 结果通常是不正确的代码与有害的竞态条件。
条件variables可以避免这个问题,因为调用cond_wait会自动释放互斥锁,释放它以供其他人使用。 在cond_wait返回之前,互斥体被重新获得。
IIRC有可能只使用信号量来实现一个condvar,但是如果你正在实现的与condvar一起使用的互斥锁需要使用trylock,那么这是一个严重的头疼的事情,定时的等待已经结束了。 不build议。 所以,不要认为你可以用condvar做任何事情都可以用信号量来完成。 另外当然互斥体可以有很好的信号量缺乏的行为,主要是避免优先级倒置。
条件允许你做一些信号量不会的事情。
例如,假设你有一些需要互斥体的代码,称为m
。 然而,它需要等到其他线程完成任务后,才会等待一个名为s
的信号量。 现在任何需要m
线程都会被阻塞,即使有m
线程正在等待s
。 这些情况可以使用条件来解决。 当你等待一个条件时,当前所持有的互斥量被释放,所以其他线程可以获得互斥量。 所以回到我们的例子,并假设使用条件c
而不是s
。 我们的线程现在获取m
,然后有条件地等待c
。 这释放m
所以其他线程可以继续。 当c
变得可用时, m
被重新获取,并且我们的原始线程可以继续快乐地继续。
条件variables还允许您让所有等待条件variables的线程通过pthread_cond_broadcast
继续。 此外,它还可以让你执行定时等待,所以你不会永远等待。
当然,有时你不需要条件variables,所以根据你的要求,其中一个可能会更好。
第二个片段是活泼的,不要这样做。
其他答案对相对优点有很好的讨论; 我只是补充一点, pthread_cond_broadcast
是条件variables的明显优势。
除此之外,我更习惯于为variables指定variables,因为它们是Java中的variables,即使它们帮助您在检查共享标志时避免竞争。
事实上,在第二个片段中,您没有任何locking来保护cam-> status的读取,所以通过数据竞赛来访问它。 在这个例子中,大多数平台都可以让你摆脱困境,但是POSIX和下一个C / C ++标准的内存模型没有明确的语义。
事实上,如果另一个线程分配一个新的凸轮结构并覆盖凸轮,一个真正的竞争条件是可能的; 等待的线程可能会看到“cam”指针的更新,而没有看到cam-> status的初始化。 事实上,在这种情况下和总体上,第二个片段是要求麻烦的。
在你的第二个片段中,你会获得大量的locking,永远不会释放它。
一般来说,你所说的状态可以完全用信号来表示,那么你就可以使用它。 锁结构的尺寸较小,并且需要较less的primefaces操作来检查/设置/释放。
否则,如果状态是复杂的,并且代码的不同部分在相同variables的不同条件下等待(例如,在这里你想要x <10;那么你想要y> x),使用cond_wait。