目录
- 生产者消费者简单模型
- 条件变量
- 信号变量
生产者消费者简单模型
//生产者消费者模型#include <stdio.h>
#include<pthread.h>
#include<stdlib.h>
#include<unistd.h>struct Node{int num;struct Node * next;
};
//头结点
struct Node * head=NULL;void * producer(void * arg){//不断创建新的节点,添加到链表中while(1){struct Node * newNode=(struct Node *)malloc(sizeof(struct Node));newNode->next=head;head=newNode;newNode->num=rand()%1000;printf("add node,num:%d,tid:%ld\n",newNode->num,pthread_self());usleep(100);}return NULL;
}void * customer(void * arg){while(1){//保存头结点的指针struct Node * tmp=head;head = head->next;printf("del node;num:%d,tid:%ld\n",tmp->num,pthread_self());free(tmp);usleep(100);}return NULL;
}int main(){//创建5个生产者线程,和5个消费者线程pthread_t ptids[5],ctids[5];for(int i=0;i<5;i++){pthread_create(&ptids[i],NULL,producer,NULL);pthread_create(&ctids[5],NULL,customer,NULL);}for(int i=0;i<5;i++){pthread_detach(ptids[i]);pthread_detach(ctids[5]);}// while(1){// sleep(10);// }pthread_exit(NULL);return 0;
}
容易出现段错误,原因就是会有几种情况:
会产生数据安全问题,比如生产者还未生产出来,就去消费。
//生产者消费者模型#include <stdio.h>
#include<pthread.h>
#include<stdlib.h>
#include<unistd.h>//创建一个互斥
pthread_mutex_t mutex;struct Node{int num;struct Node * next;
};
//头结点
struct Node * head=NULL;void * producer(void * arg){//不断创建新的节点,添加到链表中while(1){pthread_mutex_lock(&mutex);struct Node * newNode=(struct Node *)malloc(sizeof(struct Node));newNode->next=head;head=newNode;newNode->num=rand()%1000;printf("add node,num:%d,tid:%ld\n",newNode->num,pthread_self());pthread_mutex_unlock(&mutex);usleep(100);}return NULL;
}void * customer(void * arg){while(1){//保存头结点的指针pthread_mutex_lock(&mutex);struct Node * tmp=head;//判断是否有数据if(head!=NULL){//有数据head = head->next;printf("del node;num:%d,tid:%ld\n",tmp->num,pthread_self());free(tmp);pthread_mutex_unlock(&mutex);usleep(100);}else{//没有数据pthread_mutex_unlock(&mutex);}}return NULL;
}int main(){pthread_mutex_init(&mutex,NULL);//创建5个生产者线程,和5个消费者线程pthread_t ptids[5],ctids[5];for(int i=0;i<5;i++){pthread_create(&ptids[i],NULL,producer,NULL);pthread_create(&ctids[5],NULL,customer,NULL);}for(int i=0;i<5;i++){pthread_detach(ptids[i]);pthread_detach(ctids[5]);}while(1){sleep(10);}pthread_mutex_destroy(&mutex);pthread_exit(NULL);return 0;
}
解决该问题需要用互斥量确保线程同步,用条件变量或者信号量去解决生产者和消费者之间同步的问题,生产者把数据生产满了要通知消费者去消费。
条件变量
//生产者消费者模型#include <stdio.h>
#include<pthread.h>
#include<stdlib.h>
#include<unistd.h>//创建一个互斥
pthread_mutex_t mutex;
//创建条件变量
pthread_cond_t cond;struct Node{int num;struct Node * next;
};
//头结点
struct Node * head=NULL;void * producer(void * arg){//不断创建新的节点,添加到链表中while(1){pthread_mutex_lock(&mutex);struct Node * newNode=(struct Node *)malloc(sizeof(struct Node));newNode->next=head;head=newNode;newNode->num=rand()%1000;printf("add node,num:%d,tid:%ld\n",newNode->num,pthread_self());//只要生产了一个,就通知消费者消费pthread_cond_signal(&cond);pthread_mutex_unlock(&mutex);usleep(100);}return NULL;
}void * customer(void * arg){while(1){//保存头结点的指针pthread_mutex_lock(&mutex);struct Node * tmp=head;//判断是否有数据if(head!=NULL){//有数据head = head->next;printf("del node;num:%d,tid:%ld\n",tmp->num,pthread_self());free(tmp);pthread_mutex_unlock(&mutex);usleep(100);}else{//没有数据,需要等待//当wait调用阻塞的时候,会对互斥锁进行解锁,当不阻塞的时候,继续向下执行会重新加锁pthread_cond_wait(&cond,&mutex);pthread_mutex_unlock(&mutex);}}return NULL;
}int main(){pthread_mutex_init(&mutex,NULL);pthread_cond_init(&cond,NULL);//创建5个生产者线程,和5个消费者线程pthread_t ptids[5],ctids[5];for(int i=0;i<5;i++){pthread_create(&ptids[i],NULL,producer,NULL);pthread_create(&ctids[5],NULL,customer,NULL);}for(int i=0;i<5;i++){pthread_detach(ptids[i]);pthread_detach(ctids[5]);}while(1){sleep(10);}pthread_mutex_destroy(&mutex);pthread_cond_destroy(&cond);pthread_exit(NULL);return 0;
}
信号变量
//生产者消费者模型#include <stdio.h>
#include<pthread.h>
#include<stdlib.h>
#include<unistd.h>
#include<semaphore.h>//创建一个互斥
pthread_mutex_t mutex;
//创建两个信号量
sem_t psem;
sem_t csem;struct Node{int num;struct Node * next;
};
//头结点
struct Node * head=NULL;void * producer(void * arg){//不断创建新的节点,添加到链表中while(1){sem_wait(&psem);pthread_mutex_lock(&mutex);struct Node * newNode=(struct Node *)malloc(sizeof(struct Node));newNode->next=head;head=newNode;newNode->num=rand()%1000;printf("add node,num:%d,tid:%ld\n",newNode->num,pthread_self());pthread_mutex_unlock(&mutex);sem_post(&csem);usleep(100);}return NULL;
}void * customer(void * arg){while(1){sem_wait(&csem);//保存头结点的指针pthread_mutex_lock(&mutex);struct Node * tmp=head;head = head->next;printf("del node;num:%d,tid:%ld\n",tmp->num,pthread_self());free(tmp);pthread_mutex_unlock(&mutex);sem_post(&psem);}return NULL;
}int main(){pthread_mutex_init(&mutex,NULL);sem_init(&psem,0,8);sem_init(&csem,0,0);//创建5个生产者线程,和5个消费者线程pthread_t ptids[5],ctids[5];for(int i=0;i<5;i++){pthread_create(&ptids[i],NULL,producer,NULL);pthread_create(&ctids[5],NULL,customer,NULL);}for(int i=0;i<5;i++){pthread_detach(ptids[i]);pthread_detach(ctids[5]);}while(1){sleep(10);}pthread_mutex_destroy(&mutex);pthread_exit(NULL);return 0;
}