全部博文(10)
2013年(10)
分类: LINUX
2013-08-04 12:54:54
pthread_cond_wait()用法:
ptread_mutex_lock(&mut);
pthread_cond_wait(&cond, &mut);
pthread_mutex_unlock(&mut);
pthread_cond_signal(&cond);的用法和pthread_cond_wait是一样的。我们先来看看pthread_cond_wait()函数。
pthread_cond_wait(pthread_cond_t *cond, pthread_mutex_t *mutex)函数传入的参数mutex用于保护条件,因为我们在调用pthread_cond_wait时,如果条件不成立,我们就进入阻塞,但是进入阻塞期间,如果条件变量改变了的话,我们就漏掉了这个条件。因为这个线程还没有放到等待队列上,所以调用pthread_cond_wait前要先锁互斥量,即调用pthread_mutex_lock(), pthread_cond_wait在把线程放进阻塞队列后,自动对mutex进行解锁(它内部有自己维护一个队列),使得其他线程可以获得加锁的权利。这样其它线程才能对临界资源进行访问并在适当的时候唤醒这个阻塞的进程。当pthread_cond_wait返回的时候又会自动给mutex加锁,所以最后需要一个pthread_mutex_unlock()函数来解锁。
pthread_cond_signal(pthread_cond_t *cond)函数是用来在条件满足时,给正在等待的对象发送信息,表示唤醒该变量,一般和pthread_cond_wait函数联合使用,当它接收到signal发来的信号后,就再次锁住mutex,一旦pthread_cond_wait锁定了互斥对象,那么它将返回并允许wait的线程继续执行。
如下例子:
#include
#include
#include
pthread_mutex_t count_lock;
pthread_cond_t count_nonzero;
unsigned count = 0;
void * decrement_count(void *arg)
{
pthread_mutex_lock (&count_lock);
printf("decrement_count get count_lock\n");
while(count==0)
{
printf("decrement_count count == 0 \n");
printf("decrement_count before cond_wait \n");
pthread_cond_wait( &count_nonzero, &count_lock);
printf("decrement_count after cond_wait \n");
}
count = count -1;
pthread_mutex_unlock (&count_lock);
}
void * increment_count(void *arg)
{
pthread_mutex_lock(&count_lock);
printf("increment_count get count_lock\n");
if(count==0) {
printf("increment_count before cond_signal\n");
pthread_cond_signal(&count_nonzero);
printf("increment_count after cond_signal\n");
}
count=count+1;
pthread_mutex_unlock(&count_lock);
}
int main(void)
{
pthread_t tid1,tid2;
pthread_mutex_init(&count_lock,NULL);
pthread_cond_init(&count_nonzero,NULL);
pthread_create(&tid1,NULL,decrement_count,NULL);
sleep(2);
pthread_create(&tid2,NULL,increment_count,NULL);
sleep(10);
pthread_exit(0);
}
首先,让我们考虑以下情况:线程为查看已链接列表而锁定了互斥对象,然而该列表恰巧为空的,这一特定线程什么也干不了,其设计意图是从列表中除去结点,但现在却没有结点。因此,它只能:锁定互斥对象,并调用pthread_cond_wait。
它第一步是同时对互斥对象解锁(于是其他线程可以修改已链接列表),并等待条件cond发生(这样当它接收到另一个线程的“信号”时,将苏醒)。现在互斥对象已被解锁,其他线程可以访问和修改已链接列表,可能还会添加项。(要求解锁并阻塞是一个原子操作)。
此时,pthread_cond_wait调用还未返回。对互斥对象解锁会立即发生,但等待条件cond通常是一个阻塞操作,这意味着线程将睡眠,在它苏醒之前不会消耗CPU周期,线程将一直睡眠,直到特定条件发生,在这期间不会发生浪费CPU时间的繁忙查询。从线程的角度来看,它只是在等待pthread_cond_wait调用返回。
假设另一个线程(线程2)锁定了mutex并对已链接列表添加了一项。在对互斥对象解锁后,线程2会立即调用函数pthread_cond_broadcast(&cond)或者pthread_cond_signal(&cond)。此操作之后,线程2将使所有等待cond条件变量的线程立即熟悉。这意味着第一个线程(仍处于pthread_cond_wait()调用中)现在将苏醒。
然后pthread_cond_wait执行最后一个操作:重新锁定mutex,一旦它锁定了互斥对象,那么pthread_cond_wait将返回并允许线程1继续执行。此时,它可以马上检查列表,查看它所感兴趣的更改。
处理完成之后退出了函数。并调用pthread_mutex_unlock进行mutex的解锁。