pthread_cond_wait 丢失来自 pthread_cond_signal 的信号
Posted
技术标签:
【中文标题】pthread_cond_wait 丢失来自 pthread_cond_signal 的信号【英文标题】:pthread_cond_wait lost signal from pthread_cond_signal 【发布时间】:2014-04-08 14:20:36 【问题描述】:我创建了多个线程并希望使用条件变量以循环方式运行它们 和信号(pthread_cond_wait & pthread_cond_signal)。
我使用了两种方法,一种方法有效但浪费 CPU,而另一种方法无效, 不浪费 CPU。
我面临的问题是信号之前发送 我的线程在等待并且信号丢失了。所以它进入无限等待循环。
第一种方法:
线程被创建并等待条件变量并不断检查调用的变量 作为状态(在一个while循环内)。
当 state == my_id 时,带有 my_id 的线程被激活,然后它向下一个线程 my_id+1 发出信号,依此类推 开。
DRAWBACK : CPU 的浪费
第二种方法:
线程被创建并等待它自己的条件变量的信号。现在因为信号已经 在线程开始等待之前发送,信号丢失,程序进入无限等待循环。
信号丢失时是否有类似“自我信号”或其他发送信号的方式?
我在linux下使用g++。任何线索将不胜感激。提前致谢。
第一种方法的程序在这里round robin。
这是我的第二种方法的程序:
#include <pthread.h>
#include <stdio.h>
#include <iostream>
#include <mutex> // std::mutex
#define MULTIPLE_THREADS 2
#define NTHREADS MULTIPLE_THREADS*64
#define NO_OF_LOOP 1
pthread_cond_t cond[NTHREADS];
pthread_mutex_t mutex1 = PTHREAD_MUTEX_INITIALIZER;
using namespace std;
/* This is our thread function. It is like main(), but for a thread*/
void *threadA(void *arg)
long my_id = (long)arg;
int i = 0;
while(i < NO_OF_LOOP)
// Awaken or unblocked by thread (i-1)
pthread_mutex_lock(&mutex1);
pthread_cond_wait(&cond[my_id], &mutex1);
pthread_mutex_unlock(&mutex1);
printf("I am thread - %ld",my_id);
++i;
/* wake up thread i+1 */
pthread_mutex_lock(&mutex1);
pthread_cond_signal(&cond[(my_id + 1) % NTHREADS]);
pthread_mutex_unlock(&mutex1);
return NULL;
int main(void)
pthread_t threadid[NTHREADS];
// Initialization
for(int i=0;i<NTHREADS;i++)
cond[i]= PTHREAD_COND_INITIALIZER;
//printf("Create %d threads\n", NTHREADS);
for(long i=0; i<NTHREADS; ++i)
pthread_create(&threadid[i], NULL, threadA, (void *)i);
//printf("Thread created=%d\n", i);
// printf("Wait for threads and cleanup\n");
for (long i=0; i<NTHREADS; ++i)
pthread_join(threadid[i], NULL);
return 0;
【问题讨论】:
重新设计!在等待之前不要发出信号。 @Dabo 以后如何发送信号?我应该在主线程中使用一些睡眠吗? 您的互斥锁没有保护任何东西,您的线程也没有等待任何东西。 【参考方案1】:您不能以这种方式使用条件变量。你总是需要一个谓词。也就是说,你需要 您可以测试是否发生事件的变量。
简单地发出一个盲目的 pthread_cond_wait 和 pthread_cond_signal 会让你丢失事件。 可能有spurious wakeups,如果你发信号的线程没有在pthread_cond_wait()中被阻塞,它将错过事件(pthread_cond_signal()没有排队)。
您将需要这样的东西(未经测试):
pthread_cond_t cond[NTHREADS];
int wakeup[NTHREADS];
pthread_mutex_t mutex1 = PTHREAD_MUTEX_INITIALIZER;
using namespace std;
/* This is our thread function. It is like main(), but for a thread*/
void *threadA(void *arg)
long my_id = (long)arg;
int i = 0;
while(i < NO_OF_LOOP)
// Awaken or unblocked by thread (i-1)
pthread_mutex_lock(&mutex1);
while (!wakeup[my_id])
pthread_cond_wait(&cond[my_id], &mutex1);
wakeup[my_id] = 0;
pthread_mutex_unlock(&mutex1);
printf("I am thread - %ld",my_id);
++i;
pthread_mutex_lock(&mutex1);
//tell thread i to wake up
wakeup[(my_id + 1) % NTHREADS] = 1;
pthread_cond_signal(&cond[(my_id + 1) % NTHREADS]);
pthread_mutex_unlock(&mutex1);
return NULL;
int main(void)
pthread_t threadid[NTHREADS];
wakeup[0] = 1; //let thread 0 start.
编辑。 #define NTHREADS MULTIPLE_THREADS*64
宏也有另一个错误。
表达式(my_id + 1) % NTHREADS
将不会被正确计算,宏必须是
#define NTHREADS (MULTIPLE_THREADS*64)
由于标准输出通常是行缓冲的,所以在你的 printf 中添加一个换行符,这样你就可以立即看到输出。
printf("I am thread - %ld\n",my_id);
【讨论】:
感谢您解释我在第一种方法中使用的条件变量谓词的需要,您也提出了类似的建议。我有一个疑问或疑问-您不认为在检查谓词时会浪费大量 CPU 吗?顺便说一句,虽然看起来逻辑是正确的(我使用了相同的逻辑,除了我只使用了一个状态变量)但是你的代码不起作用。 @bholanath 没有浪费 CPU,pthread_cond_wait() 阻塞了线程。我不知道如何通过只有一个状态变量来完成这项工作(而且我也不确定你的意思,听起来你只有 1 个变量而不是像唤醒数组这样的数组 - 这将不行)。注意 main() 中的wakeup[0] = 1;
相当重要。
我猜它会部分因为 #define NTHREADS MULTIPLE_THREADS*64
宏,因为它不会做你想让它做的事情。始终使用括号:#define NTHREADS (MULTIPLE_THREADS*64)
我已经更改了宏,现在它正在输出。谢谢。顺便说一句,这里使用多个变量(如数组)有什么用,因为我正在使用单个变量(即状态)获取输出并检查 state == my_id 是否?
是的,我想在这个例子中这很好,如果你只想要顺序执行,只有一个具有执行 ID 的变量会这样做以上是关于pthread_cond_wait 丢失来自 pthread_cond_signal 的信号的主要内容,如果未能解决你的问题,请参考以下文章
为什么pthread_cond_wait须要传递mutex參数