我试图在pthread中编写一个简单的线程池程序.但是,似乎pthread_cond_signal不会阻塞,这会造成问题.例如,假设我有一个“生产者 – 消费者”程序:
pthread_cond_t my_cond = PTHREAD_COND_INITIALIZER; pthread_mutex_t my_cond_m = PTHREAD_MUTEX_INITIALIZER; void * liberator(void * arg) { // XXX make sure he is ready to be freed sleep(1); pthread_mutex_lock(&my_cond_m); pthread_cond_signal(&my_cond); pthread_mutex_unlock(&my_cond_m); return NULL; } int main() { pthread_t t1; pthread_create(&t1,NULL,liberator,NULL); // XXX Don't take too long to get ready. Otherwise I'll miss // the wake up call forever //sleep(3); pthread_mutex_lock(&my_cond_m); pthread_cond_wait(&my_cond,&my_cond_m); pthread_mutex_unlock(&my_cond_m); pthread_join(t1,NULL); return 0; }
如两个XXX标记中所述,如果我拿走了睡眠呼叫,那么main()可能会因为已经从liberator()中忽略了唤醒呼叫而失效.当然,睡眠不是一个非常强大的方式来确保.
在现实生活中,这将是一个工作线程,告诉管理员线程,它已准备好工作,或者管理员线程宣布新的工作可用.
你如何在pthread中可靠地执行此操作?
精
@ Borealid的回答的作品,但他对这个问题的解释可能会更好.我建议任何人看这个问题来阅读评论中的讨论,以了解发生了什么.
特别是,我自己会修改他的答案和代码示例,使之更清晰. (自从Borealid的原始答案,编译和工作,困惑了我很多)
// In main pthread_mutex_lock(&my_cond_m); // If the flag is not set,it means liberator has not // been run yet. I'll wait for him through pthread's signaling // mechanism // If it _is_ set,it means liberator has been run. I'll simply // skip waiting since I've already synchronized. I don't need to // use pthread's signaling mechanism if(!flag) pthread_cond_wait(&my_cond,&my_cond_m); pthread_mutex_unlock(&my_cond_m); // In liberator thread pthread_mutex_lock(&my_cond_m); // Signal anyone who's sleeping. If no one is sleeping yet,// they should check this flag which indicates I have already // sent the signal. This is needed because pthread's signals // is not like a message queue -- a sent signal is lost if // nobody's waiting for a condition when it's sent. // You can think of this flag as a "persistent" signal flag = 1; pthread_cond_signal(&my_cond); pthread_mutex_unlock(&my_cond_m);
解决方法
使用同步变量.
主要内容:
pthread_mutex_lock(&my_cond_m); while (!flag) { pthread_cond_wait(&my_cond,&my_cond_m); } pthread_mutex_unlock(&my_cond_m);
在线程中:
pthread_mutex_lock(&my_cond_m); flag = 1; pthread_cond_broadcast(&my_cond); pthread_mutex_unlock(&my_cond_m);