使用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)