Linux系统编程---线程同步---条件变量

1.条件变量介绍
条件变量时线程同步的另一种方式。条件变量个多个线程提供了一个会合的场所。条件变量和互斥量一起使用,允许线程以无竞争的方式等待特定条件的发生。

2.条件变量作用
互斥量和条件变量联合避免了条件竞争。
条件竞争:一个线程预备等待一个条件变量,当它在真正进入等待之前,另一个线程恰好触发了该条件。
个人理解: 线程A测试条件不满足,进而在释放锁和进入阻塞之间,其他线程触发了条件,而线程A却未知。
举例
不使用条件变量和互斥锁,直接使用互斥锁。
线程A
while ( 1 ){
   lock
    if (a == b){
       do  something
      unlock
  }
    else {
      unlock
      sleep( 3 );
   }
}
在解锁之后,进入阻塞之间,另有线程触发了条件,而线程A却不知,进而继续阻塞。
问题关键在于解锁和阻塞不是原子操作,而条件变量解决了这一问题。
while ( 1 ){
   lock
    while (a != b)
      pthread_con_wait(cond,mutex);
    do  something;
  unlock
}

3.初始化条件变量
int  pthread_cond_init(pthread_cond_t  * cv,  const  pthread_condattr_t  * cattr);

4.阻塞在条件变量上
int  pthread_cond_wait(pthread_cond_t  * cv, pthread_mutex_t  * mutex);

当条件变量为假时,该函数释放指定的mutex,同时阻塞线程。释放与阻塞操作时原子的。
当条件变量为真时,重新加锁mutex,并返回。

被阻塞的线程可以被 pthread_cond_signal函数, pthread_cond_broadcast函数唤醒,也可能在被信号中断后被唤醒。
pthread_cond_wait函数的返回并不意味着条件的值一定发生了变化,必须重新检查条件的值。
pthread_cond_wait函数返回时,相应的互斥锁将被当前线程锁定,即使是函数出错返回。

一 般一个条件表达式都是在一个互斥锁的保护下被检查。当条件表达式未被满足时,线程将仍然阻塞在这个条件变量上。当另一个线程改变了条件的值并向条件变量发 出信号时,等待在这个条件变量上的一个线程或所有线程被唤醒,接着都试图再次占有相应的互斥锁。阻塞在条件变量上的线程被唤醒以后,直到pthread_cond_wait()函数返回之前条件的值都有可能发生变化。所以函数返回以后,在锁定相应的互斥锁之前,必须重新测试条件值。最好的测试方法是循环调用pthread_cond_wait函数,并把满足条件的表达式置为循环的终止条件。
pthread_mutex_lock(); 
while  (condition_is_false) 
        pthread_cond_wait(); 
pthread_mutex_unlock();
阻塞在同一个条件变量上的不同线程被释放的次序是不一定的。
注意:pthread_cond_wait()函数是退出点,如果在调用这个函数时,已有一个挂起的退出请求,且线程允许退出,这个线程将被终止并开始执行善后处理函数, 而这时和条件变量相关的互斥锁仍将处在锁定状态。

5.阻塞一定时间在条件变量上
int  pthread_cond_timedwait(pthread_cond_t  * cv, pthread_mutex_t  * mp,
                           const  structtimespec  *  abstime); 
头文件为:# include  < time.h >

函数到了一定的时间,即使条件未发生也会解除阻塞。这个时间由参数abstime指定。函数返回时,相应的互斥锁往往是锁定的,即使是函数出错返回。

注意:pthread_cond_timedwait函数也是退出点。超时时间参数是指一天中的某个时刻。

使用举例:

pthread_timestruc_t to; to.tv_sec = time(NULL) + TIMEOUT; to.tv_nsec = 0;

超时返回的错误码是ETIMEDOUT。


6.发送信号
int  pthread_cond_signal(pthread_cond_t  * cv);
唤醒某一个阻塞在条件变量上的线程
  注意:必须在互斥锁的保护下使用相应的条件变量。 否则对条件变量的解锁有可能发生在锁定条件变量之前,从而造成死锁。

7.广播
int  pthread_cond_broadcast(pthread_cond_t  * cv); 
唤醒所有阻塞在条件变量上的线程

8.释放条件变量
int  pthread_cond_destroy(pthread_cond_t  * cv); 

 以上函数返回值
返回值
0:成功
任何其他返回值都表示错误  

9.唤醒丢失问题
在线程未获得相应的互斥锁时调用pthread_cond_signal或pthread_cond_broadcast函数可能会引起唤醒丢失问题。

唤醒丢失往往会在下面的情况下发生:
一个线程调用pthread_cond_signal或pthread_cond_broadcast函数;
另一个线程正处在测试条件变量和调用pthread_cond_wait函数之间;
没有线程正在处在阻塞等待的状态下。





评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值