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