【问题标题】:call pthread_cond_broadcast with mutex held or not?调用 pthread_cond_broadcast 是否持有互斥锁?
【发布时间】:2023-03-30 12:51:01
【问题描述】:

使用 pthread_cond_t 我们必须关联一个互斥锁,当发出条件信号时,我已经看到了诸如

之类的代码
pthread_mutex_lock(&mutex);

//code that makes condition true

pthread_cond_broadcast(&cond);
pthread_mutex_unlock(&mutex);

和

pthread_mutex_lock(&mutex);

//code that makes condition true

pthread_mutex_unlock(&mutex);
pthread_cond_broadcast(&cond);

哪一个是正确的方法? (有关系吗?)

【问题讨论】:

    标签: c locking pthreads


    【解决方案1】:

    取决于接收器在做什么(以及任何其他来源)。

    在您的第二个代码示例中,在解锁和广播之间,可能会出现一堆其他线程并执行某些组合的操作,从而再次使条件为假。然后,您将毫无意义地进行广播。而且您不一定会拥有与更改条件时相同的服务员,这可能会或可能不会影响您的设计。

    一个像样的接收器不应该关心它是否被唤醒并且条件为假,特别是如果您使用广播。只要每次将条件更改为“真”后最终都会进行广播,我很确定使用适当编写的接收器,您可以在有或没有锁定的情况下随意广播条件变量。

    所以我认为这并不重要,但我个人会在持有锁的情况下进行广播,如果只是为了避免担心的话。与“更改……一段时间后,信号”相比,“原子更改和信号”可能会简化白板上的状态图。

    两者都是正确的(与没有互斥锁的等待不同,这是不允许的),但我认为在第二种情况下想出可能出错的用途并不难,那不会一开始就错了。不过,他们可能不得不让一些服务员做一些不寻常的事情。

    规范相当含糊地说“如果需要可预测的调度行为,则该互斥锁应由调用 pthread_cond_broadcast() 或 pthread_cond_signal() 的线程锁定。”

    http://www.opengroup.org/onlinepubs/009695399/functions/pthread_cond_signal.html

    【讨论】:

    • 有同样的问题,我找到了你的答案。我已经关注了你的链接,我认为你引用的他的一点与前面的一点有关:“如果在一个条件变量上阻塞了多个线程,则调度策略将确定线程被解除阻塞的顺序。”跨度>
    • @wilx:是的,我关心的是“不可预测的调度行为”允许什么。例如,假设您有一个记录在案的调度程序,或者有一个选项,即互斥锁和条件变量根据 FIFO 选择要唤醒的线程。如果pthread_cond_signal 的调用者没有持有互斥锁,那么“神秘”的句子是否暗示行为不应该是先进先出?我会这么认为,但我不知道“可预测”的正式定义,所以这就是为什么我觉得它很神秘。除了在 RT 系统中,我总是将调度视为有点不可预测,但我不希望它变得奇怪。
    • 目前还没有已知的案例表明您的广播是在解锁之前还是之后重要。非常困难的是,如果您在解锁后将信号移动到,则可以构建会中断的代码。
    • @David:在任何 Posix 实现中都没有已知的 pthread_cond_broadcast 案例,是吗?构造 pthread_cond_signal 案例的难度是否取决于操作系统,或者所有 Posix 系统上的所有相关 condvar 实现细节实际上都相同?在回答这个问题时我不确定(而且我仍然不确定)是 Posix 实现者认为他们被一个程序赋予了多少回旋余地,这意味着不需要“可预测的调度程序行为”。
    • 如果需要可预测的调度程序行为,您必须使用线程优先级。这是您获得可预测调度程序行为的唯一方法。至于创建 pthread_cond_signal 案例,这不是实现问题,而是纯粹的语义问题。您需要根据谓词更改条件的含义,以便唤醒的“错误”线程只能在解锁后进入睡眠状态。创建这样的案例非常棘手。 (通过广播,只要正确的线程也醒来,错误的线程是否醒来就无关紧要了。)
    猜你喜欢
    • 2017-10-23
    • 2023-03-19
    • 1970-01-01
    • 1970-01-01
    • 2011-12-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多