天天看點

多線程: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_wait前要先加鎖
pthread_cond_wait内部會解鎖,然後等待條件變量被其它線程激活
pthread_cond_wait被激活後會再自動加鎖
激活線程:
加鎖(和等待線程用同一個鎖)
pthread_cond_signal發送信号
解鎖