生产者消费者简单模型
//生产者消费者模型
#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;
}