我以这段代码为例,其中创建了两个线程,然后看起来像使用 pthread_cond_wait() 来挂起该线程,直到它准备好通过使用 pthread_cond_signal() 再次工作。我的问题是如果多个线程同时等待怎么办?执行 pthread_cond_signal() 如何选择正确的线程来唤醒?有没有办法选择唤醒特定的线程?假设我有一个生产者线程,它将客户订单放入单独的队列中,其中每个队列由一个线程管理。如果两个消费者线程因队列中没有任何内容而被 wait() 挂起,但生产者线程仅将订单插入其中一个消费者队列中,我们到底如何区分呢?如果这是不可能的,那么我可以使用什么其他方法来完成我想要的事情?
这里是一个示例代码,因为 stackoverflow 喜欢代码...不太相关: 示例
#define _MULTI_THREADED
#include <pthread.h>
#include <stdio.h>
#include "check.h"
/* For safe condition variable usage, must use a boolean predicate and */
/* a mutex with the condition. */
int workToDo = 0;
pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
#define NTHREADS 2
void *threadfunc(void *parm)
{
int rc;
while (1) {
/* Usually worker threads will loop on these operations */
rc = pthread_mutex_lock(&mutex);
checkResults("pthread_mutex_lock()\n", rc);
while (!workToDo) {
printf("Thread blocked\n");
rc = pthread_cond_wait(&cond, &mutex);
checkResults("pthread_cond_wait()\n", rc);
}
printf("Thread awake, finish work!\n");
/* Under protection of the lock, complete or remove the work */
/* from whatever worker queue we have. Here it is simply a flag */
workToDo = 0;
rc = pthread_mutex_unlock(&mutex);
checkResults("pthread_mutex_lock()\n", rc);
}
return NULL;
}
int main(int argc, char **argv)
{
int rc=0;
int i;
pthread_t threadid[NTHREADS];
printf("Enter Testcase - %s\n", argv[0]);
printf("Create %d threads\n", NTHREADS);
for(i=0; i<NTHREADS; ++i) {
rc = pthread_create(&threadid[i], NULL, threadfunc, NULL);
checkResults("pthread_create()\n", rc);
}
sleep(5); /* Sleep is not a very robust way to serialize threads */
for(i=0; i<5; ++i) {
printf("Wake up a worker, work to do...\n");
rc = pthread_mutex_lock(&mutex);
checkResults("pthread_mutex_lock()\n", rc);
/* In the real world, all the threads might be busy, and */
/* we would add work to a queue instead of simply using a flag */
/* In that case the boolean predicate might be some boolean */
/* statement like: if (the-queue-contains-work) */
if (workToDo) {
printf("Work already present, likely threads are busy\n");
}
workToDo = 1;
rc = pthread_cond_signal(&cond);
checkResults("pthread_cond_broadcast()\n", rc);
rc = pthread_mutex_unlock(&mutex);
checkResults("pthread_mutex_unlock()\n", rc);
sleep(5); /* Sleep is not a very robust way to serialize threads */
}
printf("Main completed\n");
exit(0);
return 0;
}
Output:
Enter Testcase - QP0WTEST/TPCOS0
Create 2 threads
Thread blocked
Thread blocked
Wake up a worker, work to do...
Thread awake, finish work!
Thread blocked
Wake up a worker, work to do...
Thread awake, finish work!
Thread blocked
Wake up a worker, work to do...
Thread awake, finish work!
Thread blocked
Wake up a worker, work to do...
Thread awake, finish work!
Thread blocked
Wake up a worker, work to do...
Thread awake, finish work!
Thread blocked
Main completed
最佳答案
实际上,只有一个线程被唤醒,你无法控制它是哪一个。
(pthread_cond_signal
唤醒至少一个等待给定条件变量的线程,并且选择的线程由调度策略确定。)
就您的情况而言,您需要重新考虑条件变量 (condvar) 表示的“条件”的含义。
如果 condvar 确实意味着“生产者已将一个项目添加到多个队列之一,每个队列都有一个专用的消费者”,那么您应该 pthread_cond_broadcast
来唤醒每个队列的消费者并让唤醒的线程弄清楚是否有工作要做。或者,您可以将条件重新转换为“生产者已将一项添加到此队列,该队列具有专用消费者”,并为每个队列使用一个 condvar。
关于c - 理解 pthread_cond_wait() 和 pthread_cond_signal(),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20277033/