Chinaunix首页 | 论坛 | 博客
  • 博客访问: 778783
  • 博文数量: 230
  • 博客积分: 6330
  • 博客等级: 准将
  • 技术积分: 2188
  • 用 户 组: 普通用户
  • 注册时间: 2009-07-10 15:55
个人简介

脚踏实地

文章分类

全部博文(230)

文章存档

2017年(1)

2016年(7)

2015年(10)

2014年(32)

2013年(24)

2012年(33)

2011年(50)

2010年(30)

2009年(43)

分类: LINUX

2009-09-24 11:09:54

用条件变量最大的好处是可以避免忙等。相当与多线程中的信号。
条件变量是线程中的东西就是等待某一条件的发生和信号一样

以下是说明
,条件变量使我们可以睡眠等待某种条件出现。
条件变量是利用线程间共享的全局变量进行同步的一种机制,主要包括两个动作:一个线程等待"条件变量的条件成立"而挂起;另一个线程使"条件成立"(给出条件成立信号)。为了防止竞争,条件变量的使用总是和一个互斥锁结合在一起。
条件变量类型为pthread_cond_t


整个pthread_cond_wait(&mycond,&mymutex)函数的工作流程:
第一个线程首先调用:
    pthread_mutex_lock(&mymutex);
然后,它检查了列表。没有找到感兴趣的东西,于是它调用:
    pthread_cond_wait(&mycond, &mymutex);
然后,pthread_cond_wait() 调用在返回前执行许多操作:
    pthread_mutex_unlock(&mymutex);
它对 mymutex 解锁,然后进入睡眠状态,等待 mycond 以接收 POSIX 线程“信号”。一旦接收到“信号”(加引号是因为我们并不是在讨论传统的 UNIX 信号,而是来自 pthread_cond_signal() 或 pthread_cond_broadcast() 调用的信号),它就会苏醒。但 pthread_cond_wait() 没有立即返回 -- 它还要做一件事:重新锁定 mutex:
    pthread_mutex_lock(&mymutex);
pthread_cond_wait() 知道我们在查找 mymutex “背后”的变化,因此它继续操作,为我们锁定互斥对象,然后才返回。(以上步骤全为原子操作)




创建和注销
条件变量和互斥锁一样,都有静态动态两种创建方式,静态方式使用PTHREAD_COND_INITIALIZER常量,如下:
pthread_cond_t cond=PTHREAD_COND_INITIALIZER
动态方式调用pthread_cond_init()函数,API定义如下:
int pthread_cond_init(pthread_cond_t *cond, pthread_condattr_t *cond_attr)
尽管POSIX标准中为条件变量定义了属性,但在LinuxThreads中没有实现,因此cond_attr值通常为NULL,且被忽略。
注销一个条件变量需要调用pthread_cond_destroy(),只有在没有线程在该条件变量上等待的时候才能注销这个条件变量,否则返回EBUSY。API定义如下:
int pthread_cond_destroy(pthread_cond_t *cond)



等待和激发
int pthread_cond_wait(pthread_cond_t *cond, pthread_mutex_t *mutex)
int pthread_cond_timedwait(pthread_cond_t *cond, pthread_mutex_t *mutex, const struct timespec *abstime)
等待条件有两种方式:无条件等待pthread_cond_wait()和计时等待pthread_cond_timedwait(),其中计时等待方式如果在给定时刻前条件没有满足,则返回ETIMEOUT,结束等待,其中abstime以与time()系统调用相同意义的绝对时间形式出现,0表示格林尼治时间1970年1月1日0时0分0秒。
使用绝对时间而非相对时间的优点是。如果函数提前返回(很可能因为捕获了一个信号,)
无论哪种等待方式,都必须和一个互斥锁配合,以防止多个线程同时请求pthread_cond_wait()(或pthread_cond_timedwait(), 下同)的竞争条件(Race Condition)。mutex互斥锁必须是普通锁(PTHREAD_MUTEX_TIMED_NP)或者适应锁 (PTHREAD_MUTEX_ADAPTIVE_NP),且在调用pthread_cond_wait()前必须由本线程加锁 (pthread_mutex_lock()),而在更新条件等待队列以前,mutex保持锁定状态,并在线程挂起进入等待前解锁。在条件满足从而离开 pthread_cond_wait()之前,mutex将被重新加锁,以与进入pthread_cond_wait()前的加锁动作对应。
激发条件有两种形式,pthread_cond_signal()激活一个等待该条件的线程,存在多个等待线程时按入队顺序激活其中一个;而pthread_cond_broadcast()则激活所有等待线程。



其他
pthread_cond_wait()和pthread_cond_timedwait() 都被实现为取消点,因此,在该处等待的线程将立即重新运行,在重新锁定mutex后离开pthread_cond_wait(),然后执行取消动作。也就 是说如果pthread_cond_wait()被取消,mutex是保持锁定状态的,因而需要定义退出回调函数来为其解锁。

EXAMPLE
       Consider two shared variables x and y, protected by the mutex mut,  and
       a  condition  variable  cond  that is to be signaled whenever x becomes
       greater than y.
            
  int x,y;
              pthread_mutex_t mut = PTHREAD_MUTEX_INITIALIZER;
              pthread_cond_t cond = PTHREAD_COND_INITIALIZER;

   //    Waiting until x is greater than y is performed as follows:
            
  pthread_mutex_lock(&mut);
              while (x <= y) {
                      pthread_cond_wait(&cond, &mut);
              }
              /* operate on x and y */
              pthread_mutex_unlock(&mut);

   //    Modifications on x and y that may cause x  to  become  greater  than  y
     //  should signal the condition if needed:
             
pthread_mutex_lock(&mut);
              /* modify x and y */
              if (x > y) pthread_cond_broadcast(&cond);
              pthread_mutex_unlock(&mut);

 /*      If  it  can be proved that at most one waiting thread needs to be waken
       up (for instance, if there are only two threads communicating through x
       and  y),  pthread_cond_signal  can be used as a slightly more efficient
       alternative    to    pthread_cond_broadcast.      In     doubt,     use
       pthread_cond_broadcast.
       To  wait  for  x to becomes greater than y with a timeout of 5 seconds,
       do:
 */ 
              
struct timeval now;
              struct timespec timeout;
              int retcode;

              pthread_mutex_lock(&mut);
              gettimeofday(&now);
              timeout.tv_sec = now.tv_sec + 5;
              timeout.tv_nsec = now.tv_usec * 1000;
              retcode = 0;
              while (x <= y && retcode != ETIMEDOUT) {
                      retcode = pthread_cond_timedwait(&cond, &mut, &timeout);
              }
              if (retcode == ETIMEDOUT) {
                      /* timeout occurred */
              } else {
                      /* operate on x and y */
              }
              pthread_mutex_unlock(&mut);

要想知道更详细,请看  man pthread_cond_wait
阅读(1415) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~