Linux线程唤醒与等待

匿名 (未验证) 提交于 2019-12-02 21:56:30

生产者消费者模式在程序设计中出现频率非常高,经常会有线程间通过消息队列或其他共享变量进行交互的场景。而这时就会出现一个问题,消费者如何知道生产者已经生产了数据呢?有的程序会采取消费者循环判断消息队列大小是否为0,如果不为0则取出数据之类的方法。但是该种方法带来两个问题:

1. 生产者产出数据到消费者获得数据的延时较大。

2. CPU占用较高。

如果需要降低延时,则必然要提高轮询的频率,那么CPU占用就会升高。反之亦然,两者无法同时解决。

于是,唤醒等待机制就成为适合该种场景的解决方案。

该机制需要一个互斥对象以及条件变量共同完成,如下:

pthread_cond_t cond = PTHREAD_COND_INITIALIZER; pthread_mutex_t mutex;

其中条件变量使用宏结构常量进行赋值。接下来进行互斥对象与条件变量的初始化:

pthread_mutex_init(&mutex, NULL); pthread_cond_init(&cond, NULL);

生产者唤醒逻辑:

pthread_mutex_lock(&mutex);   pthread_cond_signal(&cond);    pthread_mutex_unlock(&mutex);

消费者等待逻辑:

pthread_mutex_lock(&mutex);   pthread_cond_wait(&cond, &mutex);   pthread_mutex_unlock(&mutex);

看到这里可能会有点疑问,为何除了条件变量还需要一个互斥对象呢?等待时为什么需要条件变量和互斥对象共同生效呢?

条件变量的操作也需要达到线程安全的要求,因此需要互斥对象来进行保证。避免两个线程同时操作条件变量引发问题。而通过查阅pthread_cond_wait()的相关资料可知,当程序运行到pthread_cond_wait()时,会将互斥对象锁释放,以便生产者能够顺利唤醒。而在消费者被成功唤醒,pthread_cond_wait()等待完成后,互斥对象会被重新上锁直到手动释放。

下方提供完整的DEMO以供参考:

/* test.cpp */  #include <pthread.h> #include <iostream> #include <signal.h> #include <stdlib.h>   #include <unistd.h>    using namespace std;  pthread_cond_t cond = PTHREAD_COND_INITIALIZER; pthread_mutex_t mutex;  void *ThreadFunc(void *arg) {        pthread_mutex_lock(&mutex);     /*此处等待唤醒*/   cout << "Thread sleeping..." << endl;   pthread_cond_wait(&cond, &mutex);     /*唤醒成功*/       cout << "Thread awakened!" << endl;   pthread_mutex_unlock(&mutex);    return NULL; }  int main(void) {    pthread_mutex_init(&mutex, NULL);   pthread_cond_init(&cond, NULL);    pthread_t tid;   pthread_create(&tid, NULL, ThreadFunc, NULL);      /*等待5秒再唤醒,方便观察*/   usleep(5000000);    pthread_mutex_lock(&mutex);     /*唤醒*/   pthread_cond_signal(&cond);      pthread_mutex_unlock(&mutex);    return 0; }

附上操作命令:

g++ test.cpp -o test -pthread ./test
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!