【问题标题】:How many mutex and cond variable?有多少互斥量和条件变量?
【发布时间】:2011-06-16 03:57:37
【问题描述】:

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

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

【问题讨论】:

    标签: c++ pthreads


    【解决方案1】:

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

    一个互斥体,因为有一个“事物”(即一块内存)要同步访问:所有工作人员之间的共享状态和推送工作的线程。

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


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

    无论如何,不​​要对不同的互斥锁使用相同的条件变量。

    【讨论】:

    • +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() ,它将阻塞。对于多线程环境中的任何队列,这几乎肯定是您想要的。 (您的计算机内存有限;应尽可能避免无限制地使用它。)

    如果您确实坚持使用互斥锁和条件变量,则需要两个条件,一个用于排队等待(和 deque 发送信号),另一个用于其他方式。条件分别表示“队列未满”和“队列未空”,入队/出队代码同样对称。

    【讨论】:

    • 好吧,我认为解决方案实际上并不简单。但描述肯定更易读/更详细。 +1
    【解决方案3】:

    我认为,如果您将队列组织为堆栈/链表,则可以通过互锁操作从队列中窃取工作而根本不加锁(它将需要信号量而不是条件变量来防止 cmets 中描述的问题到此答案)。

    伪代码是这样的:

    1. 候选人 = 头。
    2. if (candidate == null) wait_for_semaphore;
    3. if (candidate == InterlockedCompareExchange(head, Candidate->next, Candidate)) perform_work(candidate->data);
    4. 否则转到 1;

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

    【讨论】:

    • 不正确。如果多个线程检查candidate == null,然后多个其他线程发出条件信号,则只有一个服务员会看到信号并唤醒。您必须将互斥锁与条件变量句点结合使用。
    • 同意存在问题。不同意(至少现在)不可能。如果用线程数初始化的计数信号量替换条件变量?
    • 当然,对于队列,您可以使用信号量而不是互斥量+条件。您还可以使用管道或套接字或任意数量的不同原语。但这不是问题......(修正你的答案是正确的,我会删除我的反对票)
    • 那么问题是关于经典生产者/消费者场景的有效实施。问题中有队列。我认为在使用信号量的加载场景中不阻塞的联锁操作将比互斥锁/条件变量实现具有更高的吞吐量。如果问题是纯粹的学术问题——确定某种类型的同步原语的最小数量——那么你是对的:)
    • 删除了反对票,并为好主意 +1。 (你可以类似地使用另一个信号量来限制队列的大小,这也是一个好主意......)
    猜你喜欢
    • 2011-03-05
    • 1970-01-01
    • 2018-03-09
    • 2015-10-18
    • 1970-01-01
    • 1970-01-01
    • 2015-06-19
    • 1970-01-01
    • 2010-11-06
    相关资源
    最近更新 更多