pthread_mutex_t 和 pthread_cond_t 配合使用的簡要分析

1、需求

有消費者A和生產者B線程,共享變量n,生存者對n++,消費者對n--,消費者線程A必須要等到n>0纔可以執行下去,當然生產者B線程就執行n++,讓消費者能執行下去。

2、生產者和消費者模型中互斥鎖和條件變量的使用流程圖如下,其中藍色代表消費者的執行流,紅色是生產者的執行流。

3、幾個函數

/* 初始化一個條件變量 */
int pthread_cond_init (pthread_cond_t* cond, pthread_condattr_t *cond_attr);
 
/* 銷燬一個條件變量 */
int pthread_cond_destroy(pthread_cond_t* cond);
 
/* 令一個消費者等待在條件變量上 */
int pthread_cond_wait(pthread_cond_t *cv, pthread_mutex_t *mutex)
 
/* 生產者通知等待在條件變量上的消費者 */
int pthread_cond_signal(pthread_cond_t* cond);
 
/* 生產者向消費者廣播消息 */
int pthread_cond_broadcast(pthread_cond_t* cond);

消費者等待條件的僞代碼:

pthread_mutex_lock(&mutex); // 拿到互斥鎖,進入臨界區
while( 條件爲假)
	pthread_cond_wait(cond, mutex); // 令進程等待在條件變量上
修改條件
pthread_mutex_unlock(&mutex); // 釋放互斥鎖

生產者通知消費者的僞代碼:

pthread_mutex_lock(&mutex); // 拿到互斥鎖,進入臨界區
while( 條件爲假)
	pthread_cond_wait(cond, mutex); // 令進程等待在條件變量上
修改條件
pthread_mutex_unlock(&mutex); // 釋放互斥鎖

4、實例代碼

/***************************************************************
*  Copyright (C) 2016 chengonghao
*  All rights reserved.
*
*  [email protected]
***************************************************************/
#include <unistd.h>
#include <pthread.h>
 
#define CONSUMERS_COUNT 2	
#define PRODUCERS_COUNT 1
 
pthread_mutex_t g_mutex ;
pthread_cond_t g_cond ;
 
pthread_t g_thread[CONSUMERS_COUNT + PRODUCERS_COUNT] ;
int share_variable = 0 ;// this is the share variable, shared by consumer and producer
 
void* consumer( void* arg )
{
   int num = (int)arg ;
   while ( 1 ) 
   {
      /******* critical section begin *******/
      pthread_mutex_lock( &g_mutex ) ;
 
      // if share_variable == 0, means consumer shell stop here
      while ( share_variable == 0 )
      {
         printf( "consumer %d begin wait a condition...\n", num ) ;
         // put a thread blocked ont a condition variable( here is g_cond),
         // and unlock the mutex( here is g_mutex )
         pthread_cond_wait( &g_cond, &g_mutex ) ;
      }
      // here means n != 0 and consumer can goes on
      // consumer consumed shared variable, so the number of shared variable shell minus
      printf( "consumer %d end wait a condition...\n", num ) ;
      printf( "consumer %d begin consume product\n", num ) ;
      -- share_variable ;
 
      pthread_mutex_unlock( &g_mutex ) ;
      /******** critial section end *********/
      sleep( 1 ) ;
   }
   
   return NULL ;
}
 
void* producer( void* arg )
{
   int num = (int)arg ;
   while ( 1 )
   {
      /******* critical section begin *******/
      pthread_mutex_lock( &g_mutex ) ;
 
      // produce a shared variable
      printf( "producer %d begin produce product...\n", num ) ;
      ++ share_variable ;
      printf( "producer %d end produce product...\n", num ) ;
      // unblock threads blocked on a condition variable( here is g_cond )
      pthread_cond_signal( &g_cond ) ;
      printf( "producer %d notified consumer by condition variable...\n", num ) ;
      pthread_mutex_unlock( &g_mutex ) ;
 
      /******** critial section end *********/
      sleep( 5 ) ;
   }
   
   return 1 ;
}
 
 
int main( void )
{
   // initiate mutex
   pthread_mutex_init( &g_mutex, NULL ) ;
   // initiate condition
   pthread_cond_init( &g_cond, NULL ) ;
 
   // initiate consumer threads
   for ( int i = 0; i < CONSUMERS_COUNT; ++ i )
   {
      pthread_create( &g_thread[i], NULL, consumer, (void*)i ) ;
   }
   sleep( 1 ) ;
   // initiate producer threads
   for ( int i = 0; i < PRODUCERS_COUNT; ++ i )
   {
      pthread_create( &g_thread[i], NULL, producer, (void*)i ) ;
   }
   for ( int i = 0; i < CONSUMERS_COUNT + PRODUCERS_COUNT; ++ i ) 
   {
      pthread_join( g_thread[i], NULL ) ;
   }
 
   pthread_mutex_destroy( &g_mutex ) ;
   pthread_cond_destroy( &g_cond ) ;
}

5、執行結果

1.      第一個框,消費者 1 和0 發現share_variable == 0,於是先後等待在條件變量上;

2.      第二個框,生產者 0 開始生產共享變量,即 ++ share_variable,然後通知等待在條件變量上的消費者;

3.      第三個框,消費者 1 被生產者喚醒,開始消費共享變量,即– share_variable;

4.      第四個框,生產者 0 繼續生產共享變量,++ share_variable,然後通知等待在條件變量上的消費者;

5.      第五個框,消費者 0 被喚醒,開始消費共享變量,即– share_variable;

以此類推,以上描述簡化了拿鎖和釋放鎖的過程,可以結合上面的流程圖來理解代碼。

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章