有多少互斥和cond变量?

时间:2011-06-16 03:57:38

标签: c++ pthreads

我在pthread池上工作,将有五个独立的线程和一个队列。所有五个线程都在竞争从队列中获取作业,我知道我需要执行锁定/解锁和等待/信号的基本想法。

但我不确定我应该有多少互斥和cond变量。现在我只有一个互斥锁和cond变量,所有五个线程都会使用它。

3 个答案:

答案 0 :(得分:3)

一个互斥锁和至少一个条件变量。

一个互斥体,因为有一个“东西”(即内存块)可以同步访问:所有工作者和推动工作的线程之间的共享状态。

一个条件变量per,well,一个或多个线程需要等待的条件。至少你需要一个条件变量来等待新的工作,这里的条件是:“还有更多的东西要做吗?” (或者反过来说:“工作队列是空的吗?”)。


一个更实际的答案是,互斥体和相关条件变量之间存在一对多关系,共享状态和互斥体之间存在一对一的关系。根据您告诉我们的内容以及自学习以来,我建议您只为设计使用一个共享状态。当你需要更多的那个状态时,我建议你寻找一些更高层次的概念(例如渠道,期货/承诺)来建立抽象。

在任何情况下,不要将相同的条件变量用于不同的互斥锁。

答案 1 :(得分:2)

详细说明@ Ivan的解决方案......

您可以使用计数信号量+原子操作来创建非常有效的队列,而不是互斥+条件变量。

semaphore dequeue_sem = 0;
semaphore enqueue_sem = 37; // or however large you want to bound your queue

入队行动只是:

wait_for(enqueue_sem)
atomic_add_to_queue(element)
signal(dequeue_sem)

出队经营是:

wait_for(dequeue_sem)
element = atomic_remove_from_queue()
signal(enqueue_sem)

“atomic_add_to_queue”和“atomic_remove_from_queue”通常采用紧密循环中的原子比较和交换来实现。

除了它的对称性之外,这个公式还限制了队列的最大大小;如果一个线程在一个完整队列上调用enqueue(),它将阻塞。对于多线程环境中的任何队列,这几乎可以肯定。 (您的计算机具有有限的内存;如果可能,应尽量避免使用它。)

如果您确实坚持使用互斥锁和条件变量,则需要两个条件,一个用于排队等待(以及双向转发信号),另一个用于反过来。条件分别表示“队列未满”和“队列不为空”,并且入队/出队代码同样是对称的。

答案 2 :(得分:1)

我认为你可以通过Interlocked操作从队列中窃取工作,而不是通过Interlocked操作进行锁定(如果你将它组织为堆栈/链接列表(它将需要信号量而不是条件变量来防止注释中描述的问题)。< / p>

伪代码就是这样:

  1. candidate = head。
  2. if(candidate == null)wait_for_semaphore;
  3. if(candidate == InterlockedCompareExchange(head,candidate-&gt; next,candidate))perform_work(candidate-&gt; data);
  4. 其他转到1;
  5. 当然,在这种情况下,也应该通过InterlockedCompareExchange向队列添加工作,并发信号通知信号量。