生产者消费者模式在程序设计中出现频率非常高,经常会有线程间通过消息队列或其他共享变量进行交互的场景。而这时就会出现一个问题,消费者如何知道生产者已经生产了数据呢?有的程序会采取消费者循环判断消息队列大小是否为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(); pthread_mutex_lock(&mutex);
/*唤醒*/
pthread_cond_signal(&cond);
pthread_mutex_unlock(&mutex); return ;
}

附上操作命令:

g++ test.cpp -o test -pthread
./test

最新文章

  1. JAVA笔记 之 JDK新特性
  2. 挂多个class还是新建class —— 多用组合,少用继承
  3. std::auto_ptr
  4. poi读写word模板 / java生成word文档
  5. 比Redis更快:Berkeley DB面面观
  6. magento后台登陆被锁定 索引报错的解决:General error: 1205 Lock wait timeout
  7. POJ 2185 Milking Grid (KMP,求最小覆盖子矩阵,好题)
  8. jQuery css() 方法
  9. CSS溢出文本省略(text-overflow)
  10. JavaScript引用类型之Array数组的栈方法与队列方法
  11. WPF Image Binding Uri Source 失败解决办法
  12. Android Realm数据库使用指南
  13. VMware Workstation 12 Pro 之安装XP系统
  14. Django之ModelForm
  15. JavaScript高级编程(1)——JavaScript初识
  16. 【学习总结】Git学习-参考廖雪峰老师教程一-Git简介
  17. MongoDB 数据库
  18. HDU 1247 - Hat’s Words - [字典树水题]
  19. 运行./build.sh出现错误:bash: ./build.sh: Permission denied
  20. aes python加密

热门文章

  1. nodeJS 中mongoose操作分页
  2. Python学习 之三 Python基础&amp;运算符
  3. net core天马行空系列:原生DI+AOP实现spring boot注解式编程
  4. 开发APP必须知道的API集合,来源http://www.cnblogs.com/wikiki/p/7232388.html
  5. PicGo+GitHub:你的最佳免费图床选择!
  6. Count the string[KMP]HDU3336
  7. runnable和thread实现多线程的区别
  8. 从入门到入土的JS 随笔day01
  9. net start mysql提示:服务名无效
  10. codeforces-214(Div. 2)-C. Dima and Salad+DP恰好背包花费