可以pthread_cond_signal唤醒多个线程吗?

问题描述 投票:2回答:2

我正在研究Pthread的条件变量。当我读到pthread_cond_signal的解释时,我看到以下内容。

pthread_cond_signal()函数应解除阻塞在指定条件变量cond上阻塞的至少一个线程(如果在cond上阻塞了任何线程)。

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


En passant,我希望从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;
}
c multithreading pthreads condition-variable
2个回答
2
投票

由于spurious wake-ups pthread_cond_signal可以唤醒不止一个线程。

从glibc寻找pthread_cond_wait.c中的“虚假”字样。


waitbarrier它必须唤醒所有线程,当它们都到达那一点,因此它使用pthread_cond_broadcast


0
投票

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

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

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

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


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

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

© www.soinside.com 2019 - 2024. All rights reserved.