linux互斥锁pthread_mutex_t和条件变量pthread_cond_t的妙用

  基于生产者消费者模式的MQ(msg queue)实现了线程间通信,在生产者消费者模型中通常都会用到互斥锁pthread_mutex_t来保护共享内存资源,多个线程访问共享内核空间之前都会尝试获取mutex,如果有其他线程正在使用则当前线程进入锁等待状态。这样的机制难免会带来两个问题:
  1:如果两个线程同时获取mutex,则两个线程会进入死锁状态
  2:如果多个线程依次获取mutex,那么这些线程都会进入锁等待状态,浪费了cpu资源
  因此,我们可以使用互斥锁pthread_mutex_tpthread_cond_t配合来避免上面的问题

  简单来说这种方法的核心思路:就是调用pthread_mutex_lock(mutex)获取锁时再判断一下是否满足获取资源的条件,比如队列为空时执行get操作就是不满足条件,如果不满足条件则调用pthread_cond_wait(cond, mutex)这个函数使当前线程进入睡眠并且把mutex互斥锁释放掉,等待获取资源的条件满足时,比如队列新加了一条msg,此时其他线程会调用pthread_cond_signal()唤醒这个线程锁定mutex,这样就不会出现多个线程等待一个mutex或者死锁的情况了。
  生产者和消费者模型中互斥锁和条件变量的使用流程图如下,其中蓝色代表消费者的执行流,红色是生产者的执行流
这里写图片描述

下面是一个简单的程序示例:

#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 ) ;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值