生产者与消费者模式(线程的同步与互斥)
死锁产生的四个条件:
1、互斥使用(资源独占)
一个资源每次只能给一个进程使用
.2、不可强占(不可剥夺)
资源申请者不能强行的从资源占有者手中夺取资源,资源只能由占有者自愿释放
.3、请求和保持(部分分配,占有申请)
一个进程在申请新的资源的同时保持对原有资源的占有(只有这样才是动态申请,动态分配)
.4、循环等待
存在一个进程等待队列
{P1 , P2 , … , Pn},
其中P1等待P2占有的资源,P2等待P3占有的资源,…,Pn等待P1占有的资源,形成一个进程等待环路
生产者:生产数据
消费者:消费数据
提供场所:缓冲区,eg:超市
生产者消费者特点:三种关系,两类人,一个场所
三种关系指的是:生产者与生产者之间是互斥关系
消费者与消费者之间是互斥关系
生产者与消费者之间是同步与互斥关系
两类人:生产者,消费者
一个场所:存储数据(此处用带头单链表实现)
单生产者单消费者模式:此例取数据方式为LIFO后进先出,所取数据为最后一个生产的数据(也可选择所取数据为最先生产的数据,可自行选择)
互斥锁相关函数:
#include <pthread.h>
int pthread_mutex_destroy(pthread_mutex_t *mutex);
int pthread_mutex_init(pthread_mutex_t *restrict mutex,const pthread_mutexattr_t *restrict attr);
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
int pthread_mutex_lock(pthread_mutex_t *mutex);
int pthread_mutex_trylock(pthread_mutex_t *mutex);//非阻塞形式获取锁
int pthread_mutex_unlock(pthread_mutex_t *mutex);
//1.使用互斥锁实现#include<stdio.h>#include<malloc.h>#include<pthread.h>typedefint_dataType_;typedefint*_dataType_p_;typedefstruct_node{_dataType_data;struct_node*next;}node,*nodep,**nodepp;nodephead=NULL;pthread_mutex_tmutex=PTHREAD_MUTEX_INITIALIZER;nodepbuyNode(_dataType_val){nodeptmp=(nodep)malloc(sizeof(node));if(tmp!=NULL){tmp->data=val;tmp->next=NULL;returntmp;}returnNULL;}voidinit(nodepphead){*head=buyNode(0);}voidpush_list(nodephead,_dataType_val){nodeptmp=buyNode(val);tmp->next=head->next;head->next=tmp;}intpop_list(nodephead,_dataType_p_pval){if(head->next==NULL)return-1;nodepdel=head->next;*pval=del->data;head->next=del->next;free(del);return0;}void*product(void*arg){_dataType_i=0;while(1){sleep(1);pthread_mutex_lock(&mutex);push_list(head,i++);pthread_mutex_unlock(&mutex);}pthread_exit((void*)1);}void*consumer(void*arg){_dataType_val=0;while(1){sleep(1);pthread_mutex_lock(&mutex);if(pop_list(head,&val)==-1){pthread_mutex_unlock(&mutex);continue;}printf("data:%d\n",val);pthread_mutex_unlock(&mutex);}pthread_exit((void*)1);}intmain(){pthread_ttid1,tid2;init(&head);pthread_create(&tid1,NULL,product,NULL);pthread_create(&tid2,NULL,consumer,NULL);pthread_join(tid1,NULL);pthread_join(tid2,NULL);free(head);pthread_mutex_destroy(&mutex);return0;}
//2.使用条件变量实现生产者消费者模式
条件变量:基于互斥锁实现同步与互斥
一个条件变量总是和一个Mutex搭配使用。
一个线程可以调用pthread_cond_wait在一个Condition Variable上阻塞等待,这个函数做以下三步操作:
1. 释放Mutex
2. 阻塞等待
3. 当被唤醒时,重新获得Mutex并返回
条件变量相关函数:
#include <pthread.h>
int pthread_cond_destroy(pthread_cond_t *cond);
int pthread_cond_init(pthread_cond_t *restrict cond,const pthread_condattr_t *restrict attr);
pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
int pthread_cond_timedwait(pthread_cond_t *restrict cond,pthread_mutex_t *restrict mutex,
const struct timespec *restrict abstime);
int pthread_cond_wait(pthread_cond_t *restrict cond,pthread_mutex_t *restrict mutex);
pthread_cond_timedwait函数还有一个额外的参数可以设定等待超时,如果到达了abstime所指
定的时刻仍然没有别的线程来唤醒当前线程,就返回ETIMEDOUT。
int pthread_cond_broadcast(pthread_cond_t *cond);
int pthread_cond_signal(pthread_cond_t *cond);
一个线程可以调用pthread_cond_signal唤醒在某个Condition Variable上等待的另一个线程,也可以调用pthread_cond_broadcast唤醒在这个Condition Variable上等待的所有线程。
#include<stdio.h>#include<malloc.h>#include<pthread.h>typedefint_dataType_;typedefint*_dataType_p_;typedefstruct_node{_dataType_data;struct_node*next;}node,*nodep,**nodepp;nodephead=NULL;pthread_cond_tcond=PTHREAD_COND_INITIALIZER;pthread_mutex_tmutex=PTHREAD_MUTEX_INITIALIZER;nodepbuyNode(_dataType_val){nodeptmp=(nodep)malloc(sizeof(node));if(tmp!=NULL){tmp->data=val;tmp->next=NULL;returntmp;}returnNULL;}voidinit(nodepphead){*head=buyNode(0);}voidpush_list(nodephead,_dataType_val){nodeptmp=buyNode(val);tmp->next=head->next;head->next=tmp;}intpop_list(nodephead,_dataType_p_pval){if(head->next==NULL)return-1;nodepdel=head->next;*pval=del->data;head->next=del->next;free(del);return0;}void*product(void*arg){_dataType_i=0;while(1){sleep(1);pthread_mutex_lock(&mutex);push_list(head,i++);pthread_cond_signal(&cond);pthread_mutex_unlock(&mutex);}pthread_exit((void*)1);}void*consumer(void*arg){_dataType_val=0;while(1){sleep(1);pthread_mutex_lock(&mutex);if(pop_list(head,&val)==-1)pthread_cond_wait(&cond,&mutex);printf("data:%d\n",val);pthread_mutex_unlock(&mutex);}pthread_exit((void*)1);}intmain(){pthread_ttid1,tid2;init(&head);pthread_create(&tid1,NULL,product,NULL);pthread_create(&tid2,NULL,consumer,NULL);pthread_join(tid1,NULL);pthread_join(tid2,NULL);free(head);pthread_cond_destroy(&cond);pthread_mutex_destroy(&mutex);return0;}
//3.使用环形buf存储数据,信号量的使用
信号量相关函数:
信号量(Semaphore)和Mutex类似,表示可用资源的数量,和Mutex不同的是这个数量可以大于1
#include <semaphore.h>
int sem_init(sem_t *sem, int pshared, unsigned int value);
int sem_destroy(sem_t *sem);
int sem_wait(sem_t *sem);//类似P操作
int sem_trywait(sem_t *sem);
int sem_timedwait(sem_t *sem, const struct timespec *abs_timeout);
int sem_post(sem_t *sem);//类似V操作
#include<stdio.h>#include<pthread.h>#include<semaphore.h>#define_SEM_PRO_20#define_SEM_COM_0typedefint_dataType_;_dataType_blank[_SEM_PRO_];sem_tsem_product;sem_tsem_consumer;void*product(void*arg){intindex=0;intcount=0;while(1){sleep(rand()%5);sem_wait(&sem_product);blank[index++]=count++;sem_post(&sem_consumer);index%=_SEM_PRO_;}pthread_exit((void*)1);}void*consumer(void*arg){intindex=0;while(1){sem_wait(&sem_consumer);printf("data:%d\n",blank[index++]);sem_post(&sem_product);index%=_SEM_PRO_;}pthread_exit((void*)1);}intmain(){pthread_ttid1,tid2;sem_init(&sem_product,0,20);sem_init(&sem_consumer,0,0);pthread_create(&tid1,NULL,product,NULL);pthread_create(&tid2,NULL,consumer,NULL);pthread_join(tid1,NULL);pthread_join(tid2,NULL);sem_destroy(&sem_product);sem_destroy(&sem_consumer);return0;}
//4.多生产者,多消费者模式
#include<stdio.h>#include<pthread.h>#include<semaphore.h>#define_SEM_PRO_20#define_SEM_COM_0typedefint_dataType_;_dataType_blank[_SEM_PRO_];sem_tsem_product;sem_tsem_consumer;pthread_mutex_tmutex_product=PTHREAD_MUTEX_INITIALIZER;pthread_mutex_tmutex_consumer=PTHREAD_MUTEX_INITIALIZER;void*product(void*arg){intindex=0;intcount=0;while(1){sleep(rand()%5);sem_wait(&sem_product);pthread_mutex_lock(&mutex_product);printf("%dthreadiddoing\n",(int)arg);blank[index++]=count++;index%=_SEM_PRO_;pthread_mutex_unlock(&mutex_product);sem_post(&sem_consumer);}pthread_exit((void*)1);}void*consumer(void*arg){intindex=0;while(1){sem_wait(&sem_consumer);pthread_mutex_lock(&mutex_consumer);printf("%dthreadisconsumer,data:%d\n",(int)arg,blank[index++]);index%=_SEM_PRO_;pthread_mutex_unlock(&mutex_consumer);sem_post(&sem_product);}pthread_exit((void*)1);}intmain(){pthread_ttid1,tid2,tid3,tid4;sem_init(&sem_product,0,20);sem_init(&sem_consumer,0,0);pthread_create(&tid1,NULL,product,(void*)1);pthread_create(&tid2,NULL,consumer,(void*)2);pthread_create(&tid3,NULL,product,(void*)3);pthread_create(&tid4,NULL,consumer,(void*)4);pthread_join(tid1,NULL);pthread_join(tid2,NULL);pthread_join(tid3,NULL);pthread_join(tid4,NULL);sem_destroy(&sem_product);sem_destroy(&sem_consumer);pthread_mutex_destroy(&mutex_product);pthread_mutex_destroy(&mutex_consumer);}
运行结果显示:
声明:本站所有文章资源内容,如无特殊说明或标注,均为采集网络资源。如若本站内容侵犯了原著者的合法权益,可联系本站删除。