multithreading - 在pthread中,如何可靠地将信号传递给另一个线程?

标签 multithreading concurrency pthreads

我正在尝试在 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/

相关文章:

java - 为什么这个线程示例不起作用?都是 wait() 的

go - 为什么将遍历从 In-order 更改为 Pre/Post-order 会使答案在 "Exercise: Equivalent Binary Trees"中出错?

java - getter 上的 volatile 和 setter 上的同步是否与两者上的同步相同?

并发和 slice 迭代

c++ - 新版本的 g++ 的多线程性能下降?

c - 程序在运行过程中丢失内存引用

c - 线程中的私有(private)变量

java - 如何在Hibernate中拦截I/O db操作?

multithreading - Qt 应用程序中的线程和事件循环

java - 在 Wicket 应用程序中同时运行计时器