Linux的锁和条件变量用法 | pthread_mutex_lock | pthread_cond_signal

原文地址:  http://hi.baidu.com/hehehehello/item/01e65ec5e3a46909c710b244


本篇默认读者已经清楚多线程中的锁、互斥锁、条件变量基本概念及作用,本篇只讲怎么在C++里编程调用。互斥锁很简单,条件变量(多用于生产者-消费者模型)则细节较多,本文主要说它。


主要涉及函数

#include<pthread.h>

int pthread_mutex_lock(pthread_mutex_t *mptr); //互斥锁加锁

int pthread_mutex_unlock(pthread_mutex_t *mptr); //互斥锁解锁

int pthread_cond_signal(pthread_cond_t *cptr); //条件变量生产

int pthread_cond_wait(pthread_cond_t *cptr,pthread_mutex_t *mptr); //条件变量消费


1.互斥锁

互斥锁是要所有人抢一样东西,一个人用完之前其他人都得等着。

1)mutex_lock是阻塞加锁,即如果mptr已经被lock则等待,直到mptr被解锁。如果不希望阻塞等待,而是立即返回是否加锁成功,则使用pthread_mutext_trylock(),其返回值表示否加锁成功。

2)mutex_unlock是解锁。如果此时锁本身就是unlocked,有可能返回错误码,也可能正常返回。取决于基础库的具体实现。


2.条件变量

条件变量是要两个人相互配合,某个事情必须A做完,B才能做(比如A负责队列插入,B负责从队列取出)。正确的顺序是B先cond_wait()睡个觉,A做完,发个cond_signal(),B被唤醒继续工作。


这里一定要注意三点:

1)cond_signal() 不计数,仅唤醒一个cond_wait(),如果此时没有cond_wait()则它什么都不做!

所以要达到我们希望的效果必须B先cond_wait(),A再cond_signal()。若反过来则A的cond_signal()什么都没做,B则永远睡眠。而实际使用中保证次序肯定是开玩笑,所以需要自己维护一个计数变量count,表示当前堆积了多少A产出的产品。B在cond_wait()前先检查count是否为0,只有在count为0时才cond_wait()等待A,否则直接执行后面代码不做cond_wait()。这样A在count==0之前所做的空操作cond_signal()会以count++的形式保存下来影响B。


2)cond_wait()实际上会执行三个子操作: unlock(mutex), real_wait(), lock(mutex)

所以cond_wait()函数有两个参数,一个cond锁,一个互斥锁。cond_wait()的标准用法是:

   pthread_mutex_lock(mutex);

   pthread_cond_wait(); //此时先解开mutex锁,进入等待....被唤醒后再加上互斥锁

   count--; //do Something ...

   unlock(mutex);

猛地一看好像会死锁(mutex_lock()后就wait()了), 其实在真正等待前mutex已经被解开了,只不过唤醒后mutex又重新被锁上。


3)大杀器:即使没有cond_signal(),cond_wait() 也有可能因其它原因被唤醒

没有具体的解释,要淡定,乖乖的在判断count == 0时不用if,改用while


示例程序:

static bool alive = true;

static int count = 0;

pthread_mutex_t mutex;

pthread_cond_t cond;


void producer()

{

      pthread_mutex_lock(&mutex);  //加互斥锁

      //...do something here, queue.insert() ...or create something...

      count++;

      pthread_cond_signal(&cond);  //唤醒wait(),如果没有wait则什么都不做

      pthread_mutex_lock(&mutex); //解互斥锁

}

void consumer()

{

      pthread_mutex_lock(&mutex);//加互斥锁

      while(alive && 0 == count) {   //仅在count == 0 时才wait,而且是while()不是if()

            pthread_cond_wait(&cond, &mutex);  //内部先解互斥锁才睡眠,等唤醒后自动加回互斥锁。

      }

      //... do something here, queue.get() ... or use & delete something

      count --;

      pthread_mutex_lock(&mutex);//解互斥锁

}


参考资料:

http://sources.redhat.com/pthreads-win32/manual/pthread_mutex_init.html

http://sources.redhat.com/pthreads-win32/manual/pthread_cond_init.html

http://blog.chinaunix.net/uid-27032138-id-3301565.html


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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值