pthread_cond_signal是否可以使多个线程唤醒?

时间:2019-05-01 11:00:43

标签: c multithreading pthreads condition-variable

我正在研究Pthread的条件变量。当我阅读pthread_cond_signal的说明时,会看到以下内容。

  

pthread_cond_signal()函数应解除阻止至少一个   的          在指定的条件变量cond上阻塞的线程(如果          cond上的所有线程均被阻止。

到目前为止,我知道pthread_cond_signal()一次只能唤醒一个线程。但是,引用的解释说至少一个。这是什么意思?可以使多个线程唤醒吗?如果是,为什么会有pthread_cond_broadcast()


很高兴,我希望以下来自UNIX Systems Programming book of Robbins的代码也与我的问题有关。是否有任何原因在 waitbarrier 函数中使用作者的pthread_cond_broadcast()而不是pthread_cond_signal()作为一个次要点,为什么还需要进行 !berror 检查作为谓词的一部分?当我通过更改尝试两者时,看不到任何区别。

/*

 The program implements a thread-safe barrier by using condition variables. The limit
 variable specifies how many threads must arrive at the barrier (execute the
 waitbarrier)  before the threads are released from the barrier.
 The count variable specifies how many threads are currently waiting at the barrier.
 Both variables are declared with the static attribute to force access through
 initbarrier and waitbarrier. If successful, the initbarrier and waitbarrier
 functions return 0. If unsuccessful, these functions return a nonzero error code.

 */

#include <errno.h>
#include <pthread.h>
#include <stdio.h>

static pthread_cond_t bcond = PTHREAD_COND_INITIALIZER;
static pthread_mutex_t bmutex = PTHREAD_MUTEX_INITIALIZER;
static int count = 0;
static int limit = 0;

int initbarrier(int n) {              /* initialize the barrier to be size n */
    int error;

    if (error = pthread_mutex_lock(&bmutex))        /* couldn't lock, give up */
        return error;
    if (limit != 0) {                 /* barrier can only be initialized once */
        pthread_mutex_unlock(&bmutex);
        return EINVAL;
    }
    limit = n;
    return pthread_mutex_unlock(&bmutex);
}

int waitbarrier(void) {    /* wait at the barrier until all n threads arrive */
    int berror = 0;
    int error;

    if (error = pthread_mutex_lock(&bmutex))        /* couldn't lock, give up */
        return error;
    if (limit <=  0) {                       /* make sure barrier initialized */
        pthread_mutex_unlock(&bmutex);
        return EINVAL;
    }
    count++;
    while ((count < limit) && !berror)
        berror =  pthread_cond_wait(&bcond, &bmutex);
    if (!berror) {
        fprintf(stderr,"soner %d\n",
                (int)pthread_self());
        berror = pthread_cond_broadcast(&bcond);           /* wake up everyone */
        }
    error = pthread_mutex_unlock(&bmutex);
    if (berror)
        return berror;
    return error;
}

/* ARGSUSED */
static void *printthread(void *arg) {
    fprintf(stderr,"This is the first print of thread %d\n",
            (int)pthread_self());
    waitbarrier();
    fprintf(stderr,"This is the second print of thread %d\n",
            (int)pthread_self());
    return NULL;
}

int main(void) {
    pthread_t t0,t1,t2;

    if (initbarrier(3)) {
        fprintf(stderr,"Error initilizing barrier\n");
        return 1;
    }
    if (pthread_create(&t0,NULL,printthread,NULL))
        fprintf(stderr,"Error creating thread 0.\n");
    if (pthread_create(&t1,NULL,printthread,NULL))
        fprintf(stderr,"Error creating thread 1.\n");
    if (pthread_create(&t2,NULL,printthread,NULL))
        fprintf(stderr,"Error creating thread 2.\n");
    if (pthread_join(t0,NULL))
        fprintf(stderr,"Error joining thread 0.\n");
    if (pthread_join(t1,NULL))
        fprintf(stderr,"Error joining thread 1.\n");
    if (pthread_join(t2,NULL))
        fprintf(stderr,"Error joining thread 2.\n");
    fprintf(stderr,"All threads complete.\n");
    return 0;
}

2 个答案:

答案 0 :(得分:2)

由于spurious wake-ups pthread_cond_signal可能会唤醒多个线程。

在glibc中寻找pthread_cond_wait.c中的“虚假”一词。


waitbarrier中,必须在所有线程到达该点时唤醒所有线程,因此它使用pthread_cond_broadcast

答案 1 :(得分:0)

  

[pthread_cond_signal()]是否可以唤醒多个线程?

不能保证。在某些操作系统和硬件平台上,在某些情况下,它可以唤醒多个线程。允许唤醒多个线程,因为这赋予了实现者更多的自由,使其可以在任何给定的硬件和操作系统下以最有效的方式工作。

必须 至少唤醒一个等待线程,否则,调用它的目的是什么?

但是,如果您的应用程序需要一个可以唤醒所有等待线程的信号,那么pthread_cond_broadcast()就是这样。


很难有效地使用多处理器系统。 https://www.e-reading.club/bookreader.php/134637/Herlihy,Shavit-_The_art_of_multiprocessor_programming.pdf

出于相同的原因,大多数编程语言和库标准都允许多线程程序在行为上具有类似的自由度:允许程序在各种不同的平台上实现高性能。