日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

pthread_cond_t

發布時間:2025/3/15 编程问答 32 豆豆
生活随笔 收集整理的這篇文章主要介紹了 pthread_cond_t 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
在多線程編程下,常常出現A線程要等待B線程條件完成后再繼續進行,這里等待方式有兩種:

1.使用鎖+輪詢

使用這種方法可以很簡單的實現,但是會有一定的性能消耗,其還有一個點要好好把握,就是一次輪詢沒有結果后相隔多久進行下一次的輪詢,間隔時間太短,消耗的CPU資源較多,間隔時間太長,不能很及時的響應請求

所以這種方法不是推薦。

2.使用條件變量的線程同步(推薦)

采用阻塞和消息方式可以極大程度上減少資源的浪費以及增加實時性

線程條件變量pthread_cond_t

線程等待某個條件

int pthread_cond_timedwait(pthread_cond_t *restrict cond,pthread_mutex_t *restrict mutex,const struct timespec *restrict abstime);

int pthread_cond_wait(pthread_cond_t *restrict cond,pthread_mutex_t *restrict mutex);?

通知函數

通知所有的線程

int pthread_cond_broadcast(pthread_cond_t *cond);?

只通知一個線程

int pthread_cond_signal(pthread_cond_t *cond);?

---------------------------------------------------------------------------------

正確的使用方法


?pthread_cond_wait用法:


pthread_mutex_lock(&mutex);


while(condition_is_false)


??{


?pthread_cond_wait(&cond,&mutex);


?}


condition_is_false=true; ?//此操作是帶鎖的,也就是說只有一個線程同時進入這塊


pthread_mutex_unlock(&mutex);

?----------------------------------------------------


pthread_cond_signal用法:?


pthread_mutex_lock(&mutex);


condition_is_false=false;


pthread_cond_signal(&cond)


pthread_mutex_unlock(&mutex)

--------------------------------------------------------

?記住上面這種用法!!!可以避免誤用pthread_cond_broadcast而釋放了所有條件變量

下面是pthread_cond_XX的用法

1.初始化條件變量pthread_cond_init


#include


int pthread_cond_init(pthread_cond_t *cv,


const pthread_condattr_t *cattr);


返回值:函數成功返回0;任何其他返回值都表示錯誤


初始化一個條件變量。當參數cattr為空指針時,函數創建的是一個缺省的條件變量。否則條件變量的屬性將由cattr中的屬性值來決定。調用 pthread_cond_init函數時,參數cattr為空指針等價于cattr中的屬性為缺省屬性,只是前者不需要cattr所占用的內存開銷。這個函數返回時,條件變量被存放在參數cv指向的內存中。


可以用宏PTHREAD_COND_INITIALIZER來初始化靜態定義的條件變量,使其具有缺省屬性。這和用pthread_cond_init函數動態分配的效果是一樣的。初始化時不進行錯誤檢查。如:

pthread_cond_t cv = PTHREAD_COND_INITIALIZER;


不能由多個線程同時初始化一個條件變量。當需要重新初始化或釋放一個條件變量時,應用程序必須保證這個條件變量未被使用。


2.阻塞在條件變量上pthread_cond_wait

#include

int pthread_cond_wait(pthread_cond_t *cv,

pthread_mutex_t *mutex);

返回值:函數成功返回0;任何其他返回值都表示錯誤

函數將解鎖mutex參數指向的互斥鎖,并使當前線程阻塞在cv參數指向的條件變量上。

被阻塞的線程可以被pthread_cond_signal函數,pthread_cond_broadcast函數喚醒,也可能在被信號中斷后被喚醒。

pthread_cond_wait函數的返回并不意味著條件的值一定發生了變化,必須重新檢查條件的值。

pthread_cond_wait函數返回時,相應的互斥鎖將被當前線程鎖定,即使是函數出錯返回。


一般一個條件表達式都是在一個互斥鎖的保護下被檢查。當條件表達式未被滿足時,線程將仍然阻塞在這個條件變量上。當另一個線程改變了條件的值并向條件變量發出信號時,等待在這個條件變量上的一個線程或所有線程被喚醒,接著都試圖再次占有相應的互斥鎖。


阻塞在條件變量上的線程被喚醒以后,直到pthread_cond_wait()函數返回之前條件的值都有可能發生變化。所以函數返回以后,在鎖定相應的互斥鎖之前,必須重新測試條件值。最好的測試方法是循環調用pthread_cond_wait函數,并把滿足條件的表達式置為循環的終止條件。如:

pthread_mutex_lock();

while (condition_is_false)

pthread_cond_wait();

pthread_mutex_unlock();


阻塞在同一個條件變量上的不同線程被釋放的次序是不一定的。

注意:pthread_cond_wait()函數是退出點,如果在調用這個函數時,已有一個掛起的退出請求,且線程允許退出,這個線程將被終止并開始執行善后處理函數,而這時和條件變量相關的互斥鎖仍將處在鎖定狀態。


3.解除在條件變量上的阻塞pthread_cond_signal

#include

int pthread_cond_signal(pthread_cond_t *cv);

返回值:函數成功返回0;任何其他返回值都表示錯誤

函數被用來釋放被阻塞在指定條件變量上的一個線程。

必須在互斥鎖的保護下使用相應的條件變量。否則對條件變量的解鎖有可能發生在鎖定條件變量之前,從而造成死鎖。


喚醒阻塞在條件變量上的所有線程的順序由調度策略決定,如果線程的調度策略是SCHED_OTHER類型的,系統將根據線程的優先級喚醒線程。

如果沒有線程被阻塞在條件變量上,那么調用pthread_cond_signal()將沒有作用。


4.阻塞直到指定時間pthread_cond_timedwait


#include

#include

int pthread_cond_timedwait(pthread_cond_t *cv,

pthread_mutex_t *mp, const structtimespec * abstime);

返回值:函數成功返回0;任何其他返回值都表示錯誤

函數到了一定的時間,即使條件未發生也會解除阻塞。這個時間由參數abstime指定。函數返回時,相應的互斥鎖往往是鎖定的,即使是函數出錯返回。

注意:pthread_cond_timedwait函數也是退出點。

超時時間參數是指一天中的某個時刻。使用舉例:

pthread_timestruc_t to;

to.tv_sec = time(NULL) + TIMEOUT;

to.tv_nsec = 0;

超時返回的錯誤碼是ETIMEDOUT。


5.釋放阻塞的所有線程pthread_cond_broadcast

#include

int pthread_cond_broadcast(pthread_cond_t *cv);

返回值:函數成功返回0;任何其他返回值都表示錯誤

函數喚醒所有被pthread_cond_wait函數阻塞在某個條件變量上的線程,參數cv被用來指定這個條件變量。當沒有線程阻塞在這個條件變量上時,pthread_cond_broadcast函數無效。


由于pthread_cond_broadcast函數喚醒所有阻塞在某個條件變量上的線程,這些線程被喚醒后將再次競爭相應的互斥鎖,所以必須小心使用pthread_cond_broadcast函數。


6.釋放條件變量pthread_cond_destroy

#include

int pthread_cond_destroy(pthread_cond_t *cv);

返回值:函數成功返回0;任何其他返回值都表示錯誤

釋放條件變量。

注意:條件變量占用的空間并未被釋放。


7.喚醒丟失問題

在線程未獲得相應的互斥鎖時調用pthread_cond_signal或pthread_cond_broadcast函數可能會引起喚醒丟失問題。

喚醒丟失往往會在下面的情況下發生:

一個線程調用pthread_cond_signal或pthread_cond_broadcast函數;

另一個線程正處在測試條件變量和調用pthread_cond_wait函數之間;

沒有線程正在處在阻塞等待的狀態下


最后是兩個可以直接運行的程序,可以更好的理解條件變量的運行過程。

(注意:為了驗證整個程序的運行過程,添加了多條printf語句)

[cpp] view plaincopy print?
  • /*條件變量?
  • 互斥鎖一個明顯的缺點是它只有兩種狀態:鎖定和非鎖定。而條件變量通過允許線程阻塞和等待另一個線程發送信號的方法彌補了互斥鎖的不足,?
  • 它常和互斥鎖一起使用。使用時,條件變量被用來阻塞一個線程,當條件不滿足時,線程往往解開相應的互斥鎖并等待條件發生變化。一旦其它的?
  • 某個線程改變了條件變量,它將通知相應的條件變量喚醒一個或多個正被此條件變量阻塞的線程。這些線程將重新鎖定互斥鎖并重新測試條件是否?
  • 滿足。一般說來,條件變量被用來進行線程間的同步。?
  • cond1.c?
  • [root@mashang?smb]#?gcc?cond1.c?-o?cond1?-lpthread?
  • [root@mashang?smb]#?./cond1?
  • */???
  • #include?<stdio.h>??
  • #include?<pthread.h>??
  • #include?<unistd.h>??
  • ??
  • pthread_mutex_t?count_lock;//自旋鎖??
  • pthread_cond_t?count_nonzero;//條件鎖??
  • unsigned?count?=?0;??
  • ??
  • void?*decrement_count(void?*arg)??
  • {??
  • ????pthread_mutex_lock(&count_lock);//等待線程:1使用pthread_cond_wait前要先加鎖??
  • ????printf("decrement_count?get?count_lock\n");??
  • ????while(count?==?0)??
  • ????{??
  • ????????printf("decrement_count?count?==?0?\n");??
  • ????????printf("decrement_count?before?cond_wait?\n");??
  • ????????pthread_cond_wait(&count_nonzero,?&count_lock);//2pthread_cond_wait內部會解鎖,然后等待條件變量被其它線程激活??
  • ????????printf("decrement_count?after?cond_wait?\n");??
  • ????}??
  • ????printf("tid1:count--\n");??
  • ????count?=?count?-?1;??
  • ????printf("tid1:count=?%d?\n",?count);??
  • ????pthread_mutex_unlock(&count_lock);??
  • }??
  • ??
  • void?*increment_count(void?*arg)??
  • {??
  • ????pthread_mutex_lock(&count_lock);?????????//激活線程:1加鎖(和等待線程用同一個鎖)??
  • ????printf("increment_count?get?count_lock?\n");??
  • ????if(count?==?0)??
  • ????{??
  • ????????printf("increment_count?before?cond_signal?\n");??
  • ????????pthread_cond_signal(&count_nonzero);???????????//2pthread_cond_signal發送信號??
  • ????????printf("increment_count?after?cond_signal?\n");??
  • ????}??
  • printf("tid2:count++\n");??
  • ????count?=?count?+?1;??
  • ????printf("tid2:count=?%d?\n",?count);??
  • ????pthread_mutex_unlock(&count_lock);//3解鎖.激活線程的上面三個操作在運行時間上都在等待線程的pthread_cond_wait函數內部。??
  • }??
  • ??
  • int?main(void)??
  • {??
  • ????pthread_t?tid1,?tid2;??
  • ??
  • ????pthread_mutex_init(&count_lock,?NULL);??
  • ????pthread_cond_init(&count_nonzero,?NULL);??
  • ??
  • ????pthread_create(&tid1,?NULL,?decrement_count,?NULL);??
  • printf("tid1?decrement?is?created,begin?sleep?2s?\n");??
  • ????sleep(2);??
  • printf("after?sleep?2s,?start?creat?tid2?increment?\n");??
  • ????pthread_create(&tid2,?NULL,?increment_count,?NULL);??
  • printf("after?tid2?increment?is?created,begin?sleep?10s?\n");??
  • ????sleep(5);??
  • printf("after?sleep?5s,begin?exit!\n");??
  • ????pthread_exit(0);??
  • ??
  • ????return?0;??
  • }??
  • /*條件變量 互斥鎖一個明顯的缺點是它只有兩種狀態:鎖定和非鎖定。而條件變量通過允許線程阻塞和等待另一個線程發送信號的方法彌補了互斥鎖的不足, 它常和互斥鎖一起使用。使用時,條件變量被用來阻塞一個線程,當條件不滿足時,線程往往解開相應的互斥鎖并等待條件發生變化。一旦其它的 某個線程改變了條件變量,它將通知相應的條件變量喚醒一個或多個正被此條件變量阻塞的線程。這些線程將重新鎖定互斥鎖并重新測試條件是否 滿足。一般說來,條件變量被用來進行線程間的同步。 cond1.c [root@mashang smb]# gcc cond1.c -o cond1 -lpthread [root@mashang smb]# ./cond1 */ #include <stdio.h> #include <pthread.h> #include <unistd.h>pthread_mutex_t count_lock;//自旋鎖 pthread_cond_t count_nonzero;//條件鎖 unsigned count = 0;void *decrement_count(void *arg) {pthread_mutex_lock(&count_lock);//等待線程:1使用pthread_cond_wait前要先加鎖printf("decrement_count get count_lock\n");while(count == 0){printf("decrement_count count == 0 \n");printf("decrement_count before cond_wait \n");pthread_cond_wait(&count_nonzero, &count_lock);//2pthread_cond_wait內部會解鎖,然后等待條件變量被其它線程激活printf("decrement_count after cond_wait \n");}printf("tid1:count--\n");count = count - 1;printf("tid1:count= %d \n", count);pthread_mutex_unlock(&count_lock); }void *increment_count(void *arg) {pthread_mutex_lock(&count_lock); //激活線程:1加鎖(和等待線程用同一個鎖)printf("increment_count get count_lock \n");if(count == 0){printf("increment_count before cond_signal \n");pthread_cond_signal(&count_nonzero); //2pthread_cond_signal發送信號printf("increment_count after cond_signal \n");} printf("tid2:count++\n");count = count + 1;printf("tid2:count= %d \n", count);pthread_mutex_unlock(&count_lock);//3解鎖.激活線程的上面三個操作在運行時間上都在等待線程的pthread_cond_wait函數內部。 }int main(void) {pthread_t tid1, tid2;pthread_mutex_init(&count_lock, NULL);pthread_cond_init(&count_nonzero, NULL);pthread_create(&tid1, NULL, decrement_count, NULL); printf("tid1 decrement is created,begin sleep 2s \n");sleep(2); printf("after sleep 2s, start creat tid2 increment \n");pthread_create(&tid2, NULL, increment_count, NULL); printf("after tid2 increment is created,begin sleep 10s \n");sleep(5); printf("after sleep 5s,begin exit!\n");pthread_exit(0);return 0; }
    第二個例程:

    [cpp] view plaincopy print?
  • /*?
  • cond2.c?
  • [root@mashang?smb]#?gcc?cond2.c?-o?cond2?-lpthread?
  • [root@mashang?smb]#?./cond2???????????????????????程序運行過程:?
  • counter:?0?????????????????????????????????????????(1)開始時?counter?為0?(main)?
  • main1:?before?creating?thd1?decrement??????????????(2)創建thd1,進入線程內部:?
  • thd1?decrement?get?the?lock?????????????????????????????先鎖定互斥鎖,若counter為0,此線程被阻塞在條件變量(count_nonzero)上.?
  • thd1?decrement?before?cond_wait?????????????????????????同時釋放互斥鎖count_lock?(wait內部會先釋放鎖,等待signal激活后自動再加上鎖)?
  • main2:thd1?is?created,?begin?create?thd2?increment?(3)與此同時主程序還在運行,創建另一個線程thrd2,進入程序內部:?
  • thd2?increment?get?the?lock?????????????????????????????先鎖定互斥鎖,若counter為0,?喚醒在條件變量(count_nonzero)上的線程即thrd1?
  • thd2?increment?before?cond_signal???????????????????????但是由于有互斥鎖count_lock,thrd1還是在等待.【signal激活后,wait內部又自動加上鎖了】?
  • thd2?increment?after??cond_signal???????????????????????所以thd2繼續運行,count++,釋放互斥鎖?
  • thd2?increment:counter?=?1??
  • thd1?decrement?after?cond_wait??????????????????????thrd1由于互斥鎖釋放,重新判斷counter是不是為0,如果為0再把線程阻塞在條件變量count_nonzero上這時counter已經為1了.?
  • thd1?decrement:counter?=?0??????????????????????????所以線程繼續運行.counter--釋放互斥鎖?
  • main3:after?thd1?and?thd2,?begin?sleep?and?exit!???(4)退出后,運行主線程main?
  • */???
  • ??
  • #include?<stdio.h>??
  • #include?<pthread.h>??
  • #include?<unistd.h>??
  • ??
  • pthread_mutex_t?counter_lock;??
  • pthread_cond_t?counter_nonzero;??
  • int?counter?=?0;??
  • int?estatus?=?-1;??
  • ??
  • void?*decrement_counter(void?*argv);??
  • void?*increment_counter(void?*argv);??
  • ??
  • int?main(int?argc,?char?**argv)??
  • {??
  • ????printf("counter:?%d\n",?counter);??
  • ????pthread_t?thd1,?thd2;??
  • ????int?ret;??
  • printf("main1:?before?creating?thd1?decrement?\n");??
  • ????ret?=?pthread_create(&thd1,?NULL,?decrement_counter,?NULL);//先創建的是等待線程,用pthread_cond_wait??
  • ????if(ret){??
  • ????????perror("del:/n");??
  • ????????return?1;??
  • ????}??
  • printf("main2:thd1?is?created,?begin?create?thd2?increment?\n");??
  • ????ret?=?pthread_create(&thd2,?NULL,?increment_counter,?NULL);//后創建的是激活線程,用pthread_cond_signal??
  • ????if(ret){??
  • ????????perror("inc:?/n");??
  • ????????return?1;??
  • ????}??
  • printf("main3:after?thd1?and?thd2,?begin?sleep?and?exit!\n");??
  • ????sleep(3);??
  • ????return?0;??
  • }??
  • ??
  • void?*decrement_counter(void?*argv)??
  • {??
  • ????pthread_mutex_lock(&counter_lock);??
  • printf("thd1?decrement?get?the?lock?\n");??
  • ????while(counter?==?0)??
  • ????{??
  • ?????printf("thd1?decrement?before?cond_wait\n");??
  • ????????pthread_cond_wait(&counter_nonzero,?&counter_lock);??
  • ?????printf("thd1?decrement?after?cond_wait?\n");??
  • ????}??
  • ????counter--;??
  • ????printf("thd1?decrement:counter?=?%d?\n",?counter);??
  • ????pthread_mutex_unlock(&counter_lock);??
  • ??
  • ????return?&estatus;??
  • }??
  • ??
  • void?*increment_counter(void?*argv)??
  • {??
  • ????pthread_mutex_lock(&counter_lock);??
  • printf("thd2?increment?get?the?lock\n");??
  • ????if(counter?==?0)??
  • ????{??
  • ?????printf("thd2?increment?before?cond_signal\n");??
  • ?????pthread_cond_signal(&counter_nonzero);??
  • ?????printf("thd2?increment?after??cond_signal\n");??
  • ????}??
  • ????counter++;??
  • ????printf("thd2?increment:counter?=?%d?\n",?counter);??
  • ????pthread_mutex_unlock(&counter_lock);??
  • ??
  • ????return?&estatus;??
  • }??
  • 總結

    以上是生活随笔為你收集整理的pthread_cond_t的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。