我正在尝试在 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
中所述标记,如果我拿走sleep
调用,然后 main()
可能会因为错过了 liberator()
的叫醒电话而停顿.当然,sleep
也不是确保这一点的非常可靠的方法。在现实生活中,这将是一个工作线程告诉管理器线程它已准备好工作,或者管理器线程宣布新工作可用。
你将如何在 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);
最佳答案
使用同步变量。
在 main
:
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);
对于生产者-消费者问题,这将是消费者在缓冲区为空时休眠,而生产者在缓冲区已满时休眠。记得获取锁之前 访问全局变量。
关于multithreading - 在pthread中,如何可靠地将信号传递给另一个线程?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3402106/