前言
pthread_cond_wait函数是Linux下条件变量的函数之一,这个函数也是其中最为复杂的一个函数,其功能为:只要到这个函数,就发生阻塞,直到使用pthread_cond_signal或者pthread_cond_broadcast给条件变量发送信号,此时该线程才继续运行,其主要用三个功能:
-
阻塞等待条件变量cond
-
释放已掌握的互斥锁(解锁互斥量)相当于ptherad_mutex_unlock(&mutex);
1、2两步为一个原子操作
-
当被唤醒,pthread_cond_wait函数返回时,解除阻塞并重新申请获取互斥锁pthread_mutex_lock(&mutex);
总结一下,运行到这里就会发生阻塞与此同时开始放锁,这个两个是原子操作,同时发生。有信号发过来,函数执行完毕,重新加锁。下面结合代码讲解一下,参考自https://www.cnblogs.com/god-of-death/p/11452308.html.:
代码示例
#include<stdio.h>
#include<string.h>
#include<pthread.h>
#include<stdlib.h>
#include<unistd.h>
pthread_t tid[3];
int sum = 0;
pthread_mutex_t sumlock = PTHREAD_MUTEX_INITIALIZER; /* 静态初始化互斥量 */
pthread_cond_t cond_sum_ready = PTHREAD_COND_INITIALIZER; /* 静态初始化条件变量 */
void * t1t2(void *arg) {
int i;
long id = (long)arg;
for (i = 0; i < 60; i++) {
pthread_mutex_lock(&sumlock); /* 使用互斥量保护临界变量 */
sum++;
printf("t%ld: read sum value = %d\n", id + 1 , sum);
pthread_mutex_unlock(&sumlock);
if (sum >= 100)
pthread_cond_signal(&cond_sum_ready); /* 发送条件通知,唤醒等待线程 */
}
return NULL;
}
void * t3(void *arg) {
pthread_mutex_lock(&sumlock);
while(sum < 100 ) /* 不满足条件将一直等待 */
{
printf("Waiting the signal...\n");
pthread_cond_wait(&cond_sum_ready, &sumlock); /* 等待条件满足 */
}
sum = 0;
printf("t3: clear sum value\n");
pthread_mutex_unlock(&sumlock);
return NULL;
}
int main(void) {
int err;
long i;
for (i = 0; i < 2; i++) {
err = pthread_create(&(tid[i]), NULL, &t1t2, (void *)i); /* 创建线程 1 线程 2 */
if (err != 0) {
printf("Can't create thread :[%s]", strerror(err));
} }
err = pthread_create(&(tid[2]), NULL, &t3, NULL); /* 创建线程 3 */
if (err != 0)
printf("Can't create thread :[%s]", strerror(err));
for (i = 0; i < 3; i++)
pthread_join(tid[i], NULL);
return 0;
}
在上面这段代码中,我们先创建了三个线程,前两个线程对sum进行自增运算,由于使用了互斥锁,整个操作是安全的。第三个线程开始执行,为防止竞争,依旧加锁, 此时,sum还没加到100, 进入while循环体,打印“Waiting the signal…”后,开始执行pthread_cond_wait函数,于是就发生了上述的1、2步,线程3阻塞并放锁,线程1或线程2拿到锁继续执行,sum终于到了101,两个线程中一个开始发送信号,线程3开始执行,pthread_cond_wait函数执行完毕,结果此时sum的值已经大于100了,于是while循环结束,继续执行下面的操作。
要点
其实还是上面那3点,一定要结合代码实际进行记忆
- “Waiting the signal…”仅仅输出了一次,说明整个运行是阻塞的;
- sum增加到了100,说明这个互斥锁已经释放了,不然就会发生死锁;
- pthread_cond_wait函数返回时,还会重新加锁,不然此时就会产生竞争;
- sum肯定只会从1加到101,因此pthread_cond_wait一定先于pthread_cond_signal运行,二者的顺序必须保证,不然会一直阻塞!
版权声明:本文为qq_36763031原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。