Chinaunix首页 | 论坛 | 博客
  • 博客访问: 501797
  • 博文数量: 174
  • 博客积分: 130
  • 博客等级: 入伍新兵
  • 技术积分: 587
  • 用 户 组: 普通用户
  • 注册时间: 2011-01-12 19:39
文章分类

全部博文(174)

文章存档

2018年(2)

2016年(10)

2015年(6)

2014年(31)

2013年(92)

2012年(33)

我的朋友

分类: C/C++

2015-08-23 13:08:04

为什么线程同步的时候pthread_cond_t要和pthread_mutex_t同时使用
pthread_mutex_t count_lock;
pthread_cond_t count_nonzero;
unsigned count = 0;

decrement_count () {
    pthread_mutex_lock (&count_lock);
    while(count==0)
        pthread_cond_wait( &count_nonzero, &count_lock);

    count=count -1;
    pthread_mutex_unlock (&count_lock);
}
 
increment_count(){
    pthread_mutex_lock(&count_lock);
 
    if(count==0)
        pthread_cond_signal(&count_nonzero);
 
    count=count+1;
    pthread_mutex_unlock(&count_lock);
}

decrement_count和increment_count在两个线程A和B中被调用。
正确的情况下,如果decrement_count首先运行,那么A会被阻塞到pthread_cond_wait。随后increment_count运行,它调用pthread_cond_signal唤醒等待条件锁count_nonzero的A线程,但是A线程并不会马上执行,因为它得不到互斥锁count_lock。当B线程执行pthread_mutex_unlock之后A线程才得以继续执行。
 
如果pthread_cond_signal前后没有使用互斥锁count_lock保护,可能的情况是这样。A阻塞到 pthread_cond_wait,然后B执行到pthread_cond_signal时候,发生了线程切换,于是A被唤醒,并且发现count依然 是0,所以继续阻塞到条件锁count_nonzero上。然后B继续执行,这时候尽管count=1,A永远不会被唤醒了。这样就发生了逻辑错误。
 
当然在这个上下文中,如果把count=count+1放在函数放在pthread_cond_signal之前变成
 
increment_count(){
     count=count+1;
 
    if(count==0)
        pthread_cond_signal(&count_nonzero);
}
 
这样没有问题。但是这种方法并不能保证所有情况下都适用。于是需要用互斥锁保护条件锁相关的变量。也就是说条件锁是用来线程通讯的,但是互斥锁是为了保护这种通讯不会产生逻辑错误,可以正常工作。

一个Condition Variable总是和一个Mutex搭配使用的。一个线程可以调用pthread_cond_wait在一个Condition Variable上阻塞等待,这个函数做以下三步操作:
  1. 释放Mutex

  2. 阻塞等待

  3. 当被唤醒时,重新获得Mutex并返回

pthread_cond_timedwait函数还有一个额外的参数可以设定等待超时,如果到达了abstime所指定的时刻仍然没有别的线程来唤醒当前线程,就返回ETIMEDOUT。一个线程可以调用pthread_cond_signal唤醒在某个Condition Variable上等待的另一个线程,也可以调用pthread_cond_broadcast唤醒在这个Condition Variable上等待的所有线程
阅读(1194) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~