使用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)
相關文章
- 使用slice和條件變數實現一個簡單的多生產者多消費者佇列變數佇列
- 使用BlockQueue實現生產者和消費者模式BloC模式
- 使用Disruptor實現生產者和消費者模型模型
- Java實現生產者和消費者Java
- 生產者和消費者(.net實現)
- Linux多執行緒消費者和生產者模型例項(互斥鎖和條件變數使用)Linux執行緒模型變數
- 使用wait()與notifyAll()實現生產者與消費者模式AI模式
- Qt生產者消費者實驗(2):等待條件QWaitConditionQTAI
- Java實現生產者-消費者模型Java模型
- 「Kafka應用」PHP實現生產者與消費者KafkaPHP
- 二、(LINUX 執行緒同步) 互斥量、條件變數以及生產者消費者問題Linux執行緒變數
- java實現生產者消費者問題Java
- 九、生產者與消費者模式模式
- ActiveMQ 生產者和消費者demoMQ
- 使用ZIO-Streams的Redis Stream消費者和生產者實現原始碼Redis原始碼
- 生產者消費者模式模式
- 生產者消費者模型模型
- 使用Python佇列和多執行緒實現生產者消費者Python佇列執行緒
- python 多執行緒實現生產者與消費者模型Python執行緒模型
- linux 生產者與消費者問題Linux
- 生產消費者模式模式
- 阻塞佇列和生產者-消費者模式佇列模式
- 有名訊號量實現消費者生產者問題
- 生產者消費者問題-C++程式碼實現C++
- 什麼是阻塞佇列?如何使用阻塞佇列來實現生產者-消費者模型?佇列模型
- 生產者與消費者之Android audioAndroid
- JAVA執行緒消費者與生產者模型Java執行緒模型
- 生產者消費者模式,以及基於BlockingQueue的快速實現模式BloC
- 讀者寫者與生產者消費者應用場景
- python 生產者消費者模式Python模式
- 關於Java多執行緒實現生產者和消費者的問題Java執行緒
- C++ condition_variable 實現生產者消費者模型C++模型
- 訊號量實現生產者消費者(程式碼邏輯有問題,不適合多個消費者,不常用)
- 多生產者-消費者中假死現象的處理
- Linux下生產者與消費者的執行緒實現Linux執行緒
- PHP操作Beanstalkd佇列(2)生產者與消費者PHPBean佇列
- 插曲:Kafka的生產者案例和消費者原理解析Kafka
- 分享一個生產者-消費者的真實場景