生产者和消费者模型
来源:互联网 发布:代练游戏商场源码 编辑:程序博客网 时间:2024/04/19 19:37
一:条件变量:
我们知道多线程访问时会出现冲突的问题,为了解决这个问题我们引入互斥锁的概念,即多个线程同时访问理解资源时,获得锁多线程可以完成”读-修改-写”操作,然后释放锁给其他线程.没有获得锁的线程只能挂起等待.
与互斥锁不同,条件变量时挂起等待而不是上锁,条件变量用来自动阻塞一个线程,直到某特殊情况的发生,通常条件变量和互斥锁同时使用.
原理:条件变量是利用线程间共享的全局变量进行同步的一种机制,主要包括两个动作:一个线程等待”条件变量的条件成立”而挂起;另一个线程”条件成立”
条件的检测是在互斥锁的保护条件下进行的,如果一个条件为假,一个线程自动阻塞,并释放等待状态的互斥锁,如果一个线程改变了条件,它发关联的条件变量,唤醒一个或多个等待的线程,重新获得互斥锁,然后重新评价条件.如果梁金成共享读写的内存,条件变量可以实现这两个进程间的线程同步
初始化和释放函数:
int pthread_cond_init(pthread_cond_t *restrict cond,
const pthread_condattr_t *restrict attr);
pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
cond一般用宏来进行初始化.
int pthread_cond_destroy(pthread_cond_t *cond)
返回值:成功返回0,失败返回错误号
和Mutes的初始化和销毁类似,ptread_cond_init函数初始化一个条件变量,attr参数为NULL,则表示缺省属性,ptread_cond_destory函数销毁一个条件变量,如果条件变量是静态的,可以用宏定义初始化,等同于初始化函数,并且attr参数为NULL;
条件变量还有以下函数:
返回值:成功返回0,失败返回错误号
可见,一个条件变量总是和一个Mutex搭配使用,一个线程可以调用pthread_cond_wait在一个条件变量上阻塞等待,这个函数做以下三步操作:
1:释放Mutex
2:阻塞等待
3:当被唤醒时,重新获得Mutex并返回.
pthread_cond_timedwait函数还有一个额外的参数可以设定等待超时,如果达到abstime所指指定的时刻仍然没有别的线程来唤醒当前线程,后返回ETIMEDOUT.一个线程可以调用pthead_cond_signal唤醒在某个Condition Variable上等待的另一个线程,也可以调用pthread_cond_broadcast唤醒在这个Condition Veriable上等待的所有线程.
一个线程可以调用pthread_cond_signal唤醒在某个条件变量上等待的另一个线程,也可以调用
pthread_cond_broadcast唤醒在这个条件变量上等待的所有线程.
生产者消费者问题是同步问题中的一种常见情况,生产者消费者问题 .也称有限缓冲问题,是一个多线程同步问题.在实际运行过程中,生产者的主要作用是生成一定数量的数据放到缓冲区中,然后重复此过程,与此同时,消费者也在缓冲区消耗 这些数据.问题的关键是保证生产者不会在缓冲区满时加入数据,消费者不会在缓冲区空时消耗数据.
二:生产者消费者模型
生产者和生产者之间为互斥关系
消费者和消费者之间为互斥关系
生产者与消费者之间既有同步又有互斥关系
解耦
假设生产者和消费者分别是两个类,如果让生产者直接调用消费者的某个方法,那么生产者对于消费者就会产生依赖(也就是耦合),将来如何是消费者代码发生变化,可能会影响生产者,如果都是依赖这个缓冲区,耦合就会相应的降低
支持并发:
生产者直接调用消费者的某个方法,还有另一个弊端.由于函数调用时同步的,在消费者的方法没有返回之前,生产者只好在一边等待,但是如果消费者处理数据很慢,生产者就会浪费很多时间.
使用生产者/消费者模式之后,生产者和消费者可以是两个独立的并发主体,(常见的并发类型有进程和线程两种),生产者生产的数据放到缓冲区,就可以继续生产,基本不依赖消费者的处理速度.
支持忙闲不均
换冲区的另外一个好处是,如果生产的数据快的时候,消费者来不及处理,未处理的数据可以暂时存在缓冲区,等生产者的生产速度降低,消费者再慢慢处理数据.
基于单链表的生产者消费者模型:
#include<stdio.h>#include<stdlib.h>#include<pthread.h>#include<sys/types.h>#include<sys/stat.h>#include<unistd.h>typedef struct SlistNode{ struct SlistNode*next; int _data;}Slist;//初始化void Init(Slist*head){ if(head!=NULL) { head->next =NULL; head->_data = 0; }}Slist*head =NULL;//静态创建static pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;static pthread_cond_t producter = PTHREAD_COND_INITIALIZER;//消费者void* consumer(void *arg){ Slist *p = NULL; while(1) { pthread_mutex_lock(&lock);//加锁 while(head ==NULL) { //条件不满足,阻塞式等待 pthread_cond_wait(&producter,&lock); } //尾删 p = head; head =head->next; p->next = NULL; pthread_mutex_unlock(&lock);//释放锁 printf("Consumer success :_data is %d\n",p->_data); free(p);p = NULL; } return NULL;}//生产者void *product(void *arg){ while(1) { sleep(rand()%2); Slist*p = malloc(sizeof(Slist)); pthread_mutex_lock(&lock); Init(p); p->_data = rand()%1000; //头插 p->next = head; head= p; pthread_mutex_unlock(&lock); printf("call consumer,product success,data is:%d\n",p->_data); pthread_cond_signal(&producter); }}int main(){ pthread_t t_product; pthread_t t_consumer; pthread_create(&t_product,NULL,product,NULL);//创建线程 pthread_create(&t_consumer,NULL,consumer,NULL);//创建线程 pthread_join(t_product,NULL);//线程等待 pthread_join(t_consumer,NULL); return 0;}
- 生产者和消费者模型
- 生产者和消费者模型
- 多线程模型:生产者和消费者
- JAVA 生产者和消费者模型
- 剖析生产者和消费者模型
- 生产者消费者模型(单个生产者和单个消费者)
- 单个生产者和单个消费者模型(spsc)
- 线程之间生产者和消费者模型
- python线程和进程,生产者消费者模型
- java多线程之生产者和消费者模型
- java多线程--生产者和消费者模型
- 多线程编程之生产者和消费者模型
- 使用BlockingQueue实现生产者和消费者模型
- 例说生产者和消费者模型
- 信号量(生产者和消费者模型)
- c++11 生产者和消费者模型
- 生产者-消费者模型
- 生产者/消费者模型
- hihoCoder太阁最新面经算法竞赛题解(6)
- 精通CSS(9-捕捉BUG)&R
- 通过kmp的失配数组来求解字符串的循环节
- window.location.href传递js对象参数及获取参数
- JS函数的形参和自调用
- 生产者和消费者模型
- 【Shadowsocks】端口已占用
- kafka的相关要点总结
- easyUI的iframe子页面获取父页面元素和给父页面元素赋值
- 【Calendar】时间的比较用before()方法;
- StringUtils.isEmpty和StringUtils.isBlank用法和区别
- freecodecamp小项目---计时器
- List集合 混合存放数据 简单实现
- 1061. 判断题(15)