Linux多线程同步------条件变量
先來看下《Linux高性能服務器編程》中對條件變量的描述:
上述話可以總結為:
? ? ? ?多線程中某一個線程依賴于另外一個線程對共享數據的改變時,就可以使用條件變量!
用消費者生產者的來理解條件變量的話,就很好理解了
?取自于:條件變量基本概念和原理_相信并熱愛著的技術博客_51CTO博客_條件變量_條件變量原理
上述這位大哥說到的,在消費者生產者角度來解釋這個東西,就可以看的很透徹了,需要時喚醒,不需要時,就進行睡眠。
下面來看一下條件變量會用到的函數以及頭文件:
#include <pthread.h>? ? //頭文件,和線程創建函數所使用頭文件一模一樣
int pthread_cond_init(pthread_cond_t *cond, pthread_condattr_t *attr);? //條件變量的初始化
第一個參數為條件變量的指針,第二個參數為條件變量的屬性,一般置為NULL
?int pthread_cond_wait(pthread_cond_t *cond, pthread_mutex_t *mutex);//等待條件變量滿足,等到喚醒之后,就會啟動該線程,否則該線程一直處于阻塞狀態
第一個參數是條件變量的指針,第二個參數是互斥鎖(互斥鎖和條件變量一般一起用,為什么呢?因為互斥鎖只有兩種狀態,鎖定和沒鎖定,而條件變量則是可以通過線程之間發送信號來讓線程進行等待或是喚醒,彌補了互斥鎖單一的鎖定方式,因此互斥鎖和條件變量一般在一起使用)。
int pthread_cond_signal(pthread_cond_t *cond); ? ? ?//喚醒單個線程
int pthread_cond_broadcast(pthread_cond_t *cond); ?//喚醒所有等待的線程
int pthread_cond_destroy(pthread_cond_t *cond);? ? //條件變量的銷毀
上面這三個函數的參數都是條件變量的指針
下面來看一段代碼,它的功能是主線程往buff中寫入數據,在寫的過程中兩個子線程在等待,然后主線程寫入完成之后,子線程完成打印。然后當主線程輸入end之后,進程結束!
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <pthread.h>pthread_mutex_t mutex; //創建互斥鎖
pthread_cond_t cond; //創建條件變量char buff[128] = {0}; void* funa(void* arg)
{while( 1 ){//等待條件可用pthread_mutex_lock(&mutex);pthread_cond_wait(&cond,&mutex);pthread_mutex_unlock(&mutex);if ( strncmp(buff,"end",3) == 0 ){break;}//打印buffprintf("funa buff=%s\n",buff);}
}void * funb(void* arg)
{while( 1 ){//等待條件可用pthread_mutex_lock(&mutex);pthread_cond_wait(&cond,&mutex); //互斥鎖加鎖之后等待主線程的信號pthread_mutex_unlock(&mutex);if ( strncmp(buff,"end",3) == 0 ){break;}//打印buffprintf("funb buff=%s\n",buff);}}int main()
{pthread_cond_init(&cond,NULL);pthread_mutex_init(&mutex,NULL);pthread_t ida, idb;pthread_create(&ida,NULL,funa,NULL);pthread_create(&idb,NULL,funb,NULL);while( 1 ){//鍵盤獲取數據-bufffgets(buff,128,stdin);//通知線程 signal broadcastif ( strncmp(buff,"end",3) == 0 ){pthread_mutex_lock(&mutex); //加鎖pthread_cond_broadcast(&cond); //輸入end時喚醒所有線程 讓大家一起結束 因為線程之間都是平級的,主線程的退出不影響子線程的運行(主要是下面還有join函數在等待子線程)pthread_mutex_unlock(&mutex); //解鎖break;}pthread_mutex_lock(&mutex);pthread_cond_signal(&cond); //喚醒其中一個子線程pthread_mutex_unlock(&mutex);}pthread_join(ida,NULL);pthread_join(idb,NULL);pthread_mutex_destroy(&mutex);pthread_cond_destroy(&cond);exit(0);
}
上述代碼中兩個子線程代碼一毛一樣,那么來看看子線程中的這三行代碼:
到底有幾把鎖?? ? ? ??
????????pthread_mutex_lock(&mutex);
? ? ? ? pthread_cond_wait(&cond,&mutex);
? ? ? ? pthread_mutex_unlock(&mutex);
上述三行代碼中有幾個鎖?先思考一下
有兩個鎖,聽我來給你捋一下,隨著兩個子線程函數創建的那一刻,兩個子線程進行對互斥鎖的競爭,其中必然只有一個線程能夠拿到鎖,沒拿到鎖的那個線程就會進入阻塞,拿到鎖的哪一個線程進行枷鎖,然后到上述提出來的代碼的第二行,pthread_cond_wait(&cond,&mutex);參數中會傳入一個互斥鎖,到這行的時候,鎖其實就已經解開了,然后就會wait等待主線程中信號來喚醒該線程,另外一個線程也是如此,剛開始沒拿到鎖,但是在另外一個子線程解鎖之后,那個子線程會wait等待喚醒,這時候剛開始沒拿到鎖的線程會重復前面的操作,然后進入wait等待喚醒,但是這喚醒的時候,兩個子線程都在等待,這時候喚醒的線程的時候,會隨機喚醒其中一個線程,這時候pthread_cond_wait(&cond,&mutex);出這行代碼的時候會進行枷鎖,只有一個子線程能被喚醒,而且是隨機喚醒!沒被喚醒的線程就一直在那wait等待喚醒
總結
以上是生活随笔為你收集整理的Linux多线程同步------条件变量的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 拿什么拯救你,我的皮肤?[已扎口]
- 下一篇: 【Linux】多线程中使用fork()