多少互斥和cond变量

How many mutex and cond variable?

本文关键字:cond 变量 多少      更新时间:2023-10-16

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

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

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

一个互斥对象,因为有一个"东西"(即内存)需要同步访问:所有工作线程和推动工作的线程之间的共享状态。

一个或多个线程需要等待的每个条件都有一个条件变量。至少你需要一个用于等待新作业的条件变量,这里的条件是:"还有更多的事情要做吗?"(或者反过来:"工作队列是空的吗?")。


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

在任何情况下,都不要将同一个条件变量与不同的互斥对象一起使用。

详细介绍@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"answers"atomic_remove_from_queue"通常使用atomiccompare&在一个紧密的循环中交换。

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

如果你坚持使用互斥锁和条件变量,你需要两个条件,一个用于入队等待(和deque发出信号),另一个用于相反的方式。条件分别表示"队列未满"answers"队列未空",入队/出队代码也同样对称。

我认为,如果您将队列组织为堆栈/链表,您可以从队列中窃取工作,而不需要通过互锁操作进行锁定(它需要信号量而不是条件变量,以防止在对此答案的注释中描述的问题)。

伪代码是这样的:

  1. 候选者=头部
  2. if(candidate==null)wait_for_symaphore
  3. if(candidate==InterlockedCompareExchange(head,candidate->next,候选者))perform_work(candidate->data)
  4. 否则转到1

当然,在这种情况下,向队列中添加工作也应该通过InterlockedCompareExchange并发出信号量。