多线程:pthread_cond_wait 实现原理

函数原型

int pthread_cond_wait(pthread_cond_t *cond, pthread_mutex_t *mutex)
第一个参数为需要等待的条件,第二个参数为互斥锁

一般该函数和 int pthread_cond_signal(pthread_cond_t *cond);函数一同使用,用来唤醒在cond条件上等待且处于就绪队列的线程执行。

代码举例

#include<stdio.h>
#include<sys/types.h>
#include<stdlib.h>
#include<unistd.h>
#include<pthread.h>
 
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t  cond  = PTHREAD_COND_INITIALIZER;
 
int count = 0;
 
void *decrement(void *arg) {
    printf("in derement.\n");
    pthread_mutex_lock(&mutex);
    if (count == 0)
        pthread_cond_wait(&cond, &mutex);
    count--;
    printf("----decrement:%d.\n", count);
    printf("out decrement.\n");
    pthread_mutex_unlock(&mutex);
    return NULL;
}
 
void *increment(void *arg) {
    printf("in increment.\n");
    pthread_mutex_lock(&mutex);
    count++;
    printf("----increment:%d.\n", count);
    if (count != 0)
        pthread_cond_signal(&cond);
    printf("out increment.\n");
    pthread_mutex_unlock(&mutex);
    return NULL;
}
 
int main(int argc, char *argv[]) {
    pthread_t tid_in, tid_de;
    pthread_create(&tid_de, NULL, (void*)decrement, NULL);
    sleep(2);
    pthread_create(&tid_in, NULL, (void*)increment, NULL);
    sleep(5);
    pthread_join(tid_de, NULL);
    pthread_join(tid_in, NULL);
    pthread_mutex_destroy(&mutex);
    pthread_cond_destroy(&cond);
    return 0;
}

原理描述

我们能够发现decrement使用pthread_cond_wait之前需要先对互斥变量加锁,同时将互斥变量做为参数传入到该函数之中,为什么要做这样的锁操作呢?

这里pthread_cond_wait() 的作用非常重要 – 它是 POSIX 线程信号发送系统的核心

关于该过程在《unix高级环境编程》中的描述如下:

The mutex passed to pthread_cond_wait protects the condition.The caller passes it locked to the function, which then atomically places them calling thread on the list of threads waiting for the condition and unlocks the mutex. This closes the window between the time that the condition is checked and the time that the thread goes to sleep waiting for the condition to change, so that the thread doesn’t miss a change in the condition. When pthread_cond_wait returns, the mutex is again locked

大体意思如下:
pthread_cond_wait函数传入的参数mutex用于保护条件,因为我们在调用pthread_cond_wait时,如果条件不成立我们就进入阻塞,但是进入阻塞这个期间,如果条件变量改变了的话(假如多个唤醒信号所处线程并行执行),那我们就漏掉了这个条件。但此时这个线程还没有放到等待队列上,所以就无法执行phtread_cond_wait所处线程。

解决办法即调用pthread_cond_wait前要先锁互斥量,即调用pthread_mutex_lock(),pthread_cond_wait在把线程放进阻塞队列后,自动对mutex进行解锁,使得其它线程可以获得加锁的权利。这样其它线程才能对临界资源进行访问并在适当的时候唤醒这个阻塞的进程,当pthread_cond_wait返回的时候又自动给mutex加锁。

所以以上代码中pthread_cond_waitpthread_cond_signal配对使用过程如下

pthread_cond_wait前要先加锁
pthread_cond_wait内部会解锁,然后等待条件变量被其它线程激活
pthread_cond_wait被激活后会再自动加锁
激活线程:
加锁(和等待线程用同一个锁)
pthread_cond_signal发送信号
解锁

激活线程的上面三个操作在运行时间上都在等待线程的pthread_cond_wait函数内部

发布了239 篇原创文章 · 获赞 17 · 访问量 3万+

猜你喜欢

转载自blog.csdn.net/Z_Stand/article/details/104309019