【问题标题】:What happens to a thread calling pthread_cond_signal?调用 pthread_cond_signal 的线程会发生什么?
【发布时间】:2019-11-28 11:28:59
【问题描述】:

当一个线程调用pthread_cond_signal 时,等待条件的线程之一将恢复其执行。但是调用线程会发生什么?它是否等待被调用线程释放互斥锁然后恢复?

例如等待线程:

pthread_mutex_lock(&mut);
// ...
pthread_cond_wait(&cond, &mut);
// ...
pthread_mutex_unlock(&mut);

还有信号线程:

pthread_mutex_lock(&mut);
// ...
pthread_cond_signal(&cond);
// ... has work to finish
pthread_mutex_unlock(&mut);

在这种情况下,如果等待线程已经接管了互斥体,信号线程如何继续工作?

【问题讨论】:

    标签: multithreading pthreads mutex condition-variable


    【解决方案1】:

    调用pthread_cond_signal 的线程立即返回。它不会等待被唤醒的线程(如果有的话)做任何事情。

    如果你调用pthread_cond_signal同时持有阻塞线程正在使用的互斥锁pthread_cond_wait,那么阻塞线程可能会从条件变量等待中唤醒,然后立即阻塞等待获取互斥锁,因为信号线程仍然持有锁。

    为了获得最佳性能,您应该在调用 pthread_cond_signal 之前解锁互斥锁。

    此外,pthread_cond_wait 可能会返回,即使没有线程已向条件变量发出信号。这被称为“虚假唤醒”。您通常需要在循环中使用pthread_cond_wait

    pthread_mutex_lock(&mut);
    while(!ready){
        pthread_cond_wait(&cond,&mut);
    }
    // do stuff
    pthread_mutex_unlock(&mut);
    

    然后信号线程在发出信号之前设置标志:

    pthread_mutex_lock(&mut);
    ready=1
    pthread_mutex_unlock(&mut);
    pthread_cond_signal(&cond);
    

    【讨论】:

    • 需要注意的是,如果需要公平/先进先出的服务员排队,那么在调用pthread_cond_signal时必须锁定互斥锁。否则,在互斥锁解锁后,另一个线程可以跳过等待者队列。
    • 我并不清楚为什么在发出信号之前解锁互斥锁可以提供任何性能改进。假设信号线程最初锁定了互斥锁,它必须同时向 CV 发出信号并解锁互斥锁,等待线程才能继续。为什么这两个操作的顺序会对性能产生影响?
    • 如果它首先发出信号,并且等待线程快速唤醒,那么等待线程现在必须阻塞互斥体,这可能是内核调用,因此速度很慢。如果信号线程首先解锁互斥锁,那么当它向条件变量发出信号时,等待线程可能会立即获取互斥锁而不会阻塞,从而避免内核调用。
    • 在“使用 POSIX 线程编程”中,David R. Butenhof 写道,一些操作系统实现了“等待变形”:在pthread_cond_signal 时,等待者线程不会立即被唤醒,而是被移入关联的互斥等待队列(假设互斥锁被锁定,我想)。我在 Linux 源代码中查找过,但找不到类似的内容。
    • 是的,这是操作系统可能执行的优化。
    猜你喜欢
    • 2012-05-17
    • 2011-09-25
    • 2013-10-13
    • 2018-03-27
    • 2015-06-05
    • 1970-01-01
    • 1970-01-01
    • 2022-09-29
    • 1970-01-01
    相关资源
    最近更新 更多