使用pthread_mutex_t与条件变量pthread_cond_t的组合来实现生产者和消费者

使用pthread_mutex_t与条件变量pthread_cond_t的组合来实现生产者和消费者;以下是基本的流程图:

#include <time.h>
#include <sys/time.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <errno.h>
#include <unistd.h>
#include <assert.h>
#include <signal.h>
#include <semaphore.h>
#include <pthread.h>

#define SUCCESS 0
#define FAILE   -1
#define true 1
#define false 0
//此次是多个消费者对应一个生产者的模型、
//使用的是互斥量pthread_mutex_t与条件变量pthread_cond_t的组合来实现,导入pthread_cond_t主要是能避免多线程带来的死锁的问题
#define CONSUMERS_COUNT 3
#define PRODUCERS_COUNT 1

typedef struct tag_THREAD_S
{
    pthread_t             tBaseTh_id[CONSUMERS_COUNT+PRODUCERS_COUNT];
    pthread_mutex_t       m_Base_lock;
    pthread_cond_t        c_Base_cond;
    int                   bBaseThdStartFlg;
}THREAD_S;

THREAD_S s_BaseThread;
int share_variable = 0 ;//生产的产品

void *ThreadConsumerFun(void *pvoid){//消费者
	//struct timespec ts;
	int num = (int*)pvoid;
    
	while(s_BaseThread.bBaseThdStartFlg){
		 pthread_mutex_lock(&s_BaseThread.m_Base_lock);
		 while ( share_variable == 0 ){
         	printf( "consumer :%d begin wait a condition...\n", num ) ;
         	pthread_cond_wait( &s_BaseThread.c_Base_cond, &s_BaseThread.m_Base_lock );//等待条件变量的时候会解锁互斥锁m_Base_lock
         	//sleep():线程等待,等待期间线程无法唤醒;(注意是期间);
			//pthread_cond_wait ;线程等待信号触发,如果没有信号触发,无限期等待下去;
			//pthread_cond_timedwait :线程等待一定的时间,如果超时或有信号触发,线程唤醒;
			//详细区别和应用可参考博客:https://www.cnblogs.com/yuanchenhui/p/thread_signal.html
       	 }
      	 share_variable--;//消费了
      	 printf( "consumer :%d end consumer.\n", num ) ;
		 pthread_mutex_unlock(&s_BaseThread.m_Base_lock);
		 sleep(6);
	}
	sleep(1);
}

void *ThreadProducerFun(void *pvoid){//生产者
	//struct timespec ts;
	int num = (int*)pvoid;
    
	while(s_BaseThread.bBaseThdStartFlg){
		 pthread_mutex_lock(&s_BaseThread.m_Base_lock);
		 printf( "producer :%d begin produce product...\n", num );
      	 share_variable++;
      	 printf( "producer :%d end produce product...\n", num );
      	 pthread_mutex_unlock( &s_BaseThread.m_Base_lock );//这一步要先于pthread_cond_signal;
      	 pthread_cond_signal( &s_BaseThread.c_Base_cond );
      	 printf( "producer: %d to notified consumer the condition variable...\n", num );
		 sleep(1);
	}
	sleep(1);
}

int Base_int(void){
	int ret=0;
	printf( "init .\n" );
	//int pthread_mutex_init(pthread_mutex_t *restrict mutex, const pthread_mutexattr_t *restrict attr);//函数原形
	pthread_mutex_init(&s_BaseThread.m_Base_lock,NULL);//初始化互斥锁
    pthread_condattr_t condAttr;
    (void)pthread_condattr_init(&condAttr);
	//(void)pthread_condattr_setclock(&condAttr, CLOCK_MONOTONIC);//设置并同步系统时间
    (void)pthread_cond_init(&s_BaseThread.c_Base_cond, &condAttr);
    (void)pthread_condattr_destroy(&condAttr);
    //int pthread_mutex_lock(pthread_mutex_t *mutex);//原形
    //int pthread_mutex_trylock(pthread_mutex_t *mutex);//不阻塞
	pthread_mutex_lock(&s_BaseThread.m_Base_lock);
    s_BaseThread.bBaseThdStartFlg = true;
    //int pthread_mutex_unlock(pthreadd_mutex_t *mutex);
    pthread_mutex_unlock(&s_BaseThread.m_Base_lock);
	return ret;
}

int Base_Deint(void){
	int ret =0;
	int i =0;
	printf( "Deinit .\n" );
	pthread_mutex_lock(&s_BaseThread.m_Base_lock);
	s_BaseThread.bBaseThdStartFlg = false;
	//pthread_cond_signal(&s_BaseThread.c_Base_cond);//发送信号;
	pthread_mutex_unlock(&s_BaseThread.m_Base_lock);
	for(i=0;i<CONSUMERS_COUNT+PRODUCERS_COUNT;i++){
		if (-1 != s_BaseThread.tBaseTh_id[i])
		{
			 pthread_join(s_BaseThread.tBaseTh_id[i], NULL);//线程连接,当前线程阻塞,等待edog线程结束才会继续运行;
			 s_BaseThread.tBaseTh_id[i]= -1;
		}
	}
	//int pthread_mutex_destroy(pthread_mutex_t *mutex);
	pthread_mutex_destroy(&s_BaseThread.m_Base_lock);//销毁互斥锁
	pthread_cond_destroy(&s_BaseThread.c_Base_cond);//销毁信号量
	memset(&s_BaseThread, 0, sizeof(THREAD_S));//复位归零
	return ret;
}

int main(){

	int ret=0;
	int i=0;
	ret=Base_int();
	if(ret){
		printf("init error!\n");
	}
	for(i=0;i<CONSUMERS_COUNT;i++){//创建消费者
		ret = pthread_create(&s_BaseThread.tBaseTh_id[i], NULL, ThreadConsumerFun,(void*)i);
		if(SUCCESS != ret)//创建失败
		{
		    printf("create ThreadConsumerFun:%d failed ! ret %d\n", i,ret);
			pthread_mutex_lock(&s_BaseThread.m_Base_lock);
		    s_BaseThread.bBaseThdStartFlg = false;
		    pthread_mutex_unlock(&s_BaseThread.m_Base_lock);
		    
		    pthread_mutex_destroy(&s_BaseThread.m_Base_lock);
		    pthread_cond_destroy(&s_BaseThread.c_Base_cond);
		    return ret;  
		}
	}

	for(i=CONSUMERS_COUNT;i<CONSUMERS_COUNT+PRODUCERS_COUNT;i++){//创建生产者
		ret = pthread_create(&s_BaseThread.tBaseTh_id[i], NULL, ThreadProducerFun, (void*)(i-CONSUMERS_COUNT));
		if(SUCCESS != ret)//创建失败
		{
		    printf("create ThreadProducerFun :%d failed ! ret %d\n",(i-CONSUMERS_COUNT), ret);
			pthread_mutex_lock(&s_BaseThread.m_Base_lock);
		    s_BaseThread.bBaseThdStartFlg = false;
		    pthread_mutex_unlock(&s_BaseThread.m_Base_lock);
		    
		    pthread_mutex_destroy(&s_BaseThread.m_Base_lock);
		    pthread_cond_destroy(&s_BaseThread.c_Base_cond);
		    return ret;  
		}
	}

	for ( i = 0; i < CONSUMERS_COUNT + PRODUCERS_COUNT; i++ ) 
   	{
      pthread_join( s_BaseThread.tBaseTh_id[i], NULL );
   	}

    while(1){
    	sleep(2);

    }

    //退出前Deinit
    ret=Base_Deint();
    if(ret){
    	printf(" Deint error !\n");
    }
	return 0;
}

运行结果:(我改变了sleep参数,这结果表明生产者生产的是充足的,即share_variable 后续没有为0)

 

 

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值