等待线程
1。使用pthread_cond_wait前要先加锁 2。pthread_cond_wait内部会解锁,然后等待条件变量被其它线程激活 3。pthread_cond_wait被激活后会再自动加锁 激活线程: 1。加锁(和等待线程用同一个锁) 2。pthread_cond_signal发送信号 3。解锁 激活线程的上面三个操作在运行时间上都在等待线程的pthread_cond_wait函数内部。 程序示例: #include <stdio.h> #include <pthread.h> #include <unistd.h> 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); } 2.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(){
} 这样没有问题。但是这种方法并不能保证所有情况下都适用。于是需要用互斥锁保护条件锁相关的变量。也就是说条件锁是用来线程通讯的,但是互斥锁是为了保护这种通讯不会产生逻辑错误,可以正常工作。
|
|
来自: ColonelLee > 《多线程》