歡迎來到Linux教程網
Linux教程網
Linux教程網
Linux教程網
Linux教程網 >> Linux基礎 >> Linux技術 >> pthread_cond_broadcast相關

pthread_cond_broadcast相關

日期:2017/3/3 12:39:12   编辑:Linux技術
pthread_cond_timedwait()函數阻塞住調用該函數的線程,等待由cond指定的條件被觸發(pthread_cond_broadcast() or pthread_cond_signal())。
當pthread_cond_timedwait()被調用時,調用線程必須已經鎖住了mutex。函數pthread_cond_timedwait()會對mutex進行【解鎖和執行對條件的等待】(原子操作)。這裡的原子意味著:解鎖和執行條件的等待是原則的,一體的。(In this case, atomically means with respect to the mutex and the condition variable and other access by threads to those objects
through the pthread condition variable interfaces.)
如果等待條件滿足或超時,或線程被取消,調用線程需要在線程繼續執行前先自動鎖住mutex,如果沒有鎖住mutex,產生EPERM錯誤。即,該函數返回時,mutex已經被調用線程鎖住。
等待的時間通過abstime參數(絕對系統時間,過了該時刻就超時)指定,超時則返回ETIMEDOUT錯誤碼。開始等待後,等待時間不受系統時鐘改變的影響。
盡管時間通過秒和納秒指定,系統時間是毫秒粒度的。需要根據調度和優先級原因,設置的時間長度應該比預想的時間要多或者少點。可以通過使用系統時鐘接口gettimeofday()獲得timeval結構體。
多線程編程中,線程A循環計算,然後sleep一會接著計算(目的是減少CPU利用率);存在的問題是,如果要關閉程序,通常選擇join線程A等待線程A退出,可是我們必須等到sleep函數返回,該線程A才能正常退出,這無疑減慢了程序退出的速度。當然,你可以terminate線程A,但這樣做很不優雅,且會存在一些未知問題。采用pthread_cond_timedwait(pthread_cond_t
* cond, pthread_mutex_t *mutex, const struct timespec * abstime)可以優雅的解決該問題,設置等待條件變量cond,如果超時,則返回;如果等待到條件變量cond,也返回。本文暫不將內部機理,僅演示一個demo
[cpp] view
plain copy
static unsigned char flag = 1;
void * thr_fn(void * arg)
{
while (flag)
{
printf(“thread sleep 10 second\n”);
sleep(10);
}
printf(“thread exit\n”);
}
int main()
{
pthread_t thread;
if (0 != pthread_create(&thread, NULL, thr_fn, NULL))
{
printf(“error when create pthread,%d\n”, errno);
return 1;
}
char c ;
while ((c = getchar()) != ‘q’);
printf(“Now terminate the thread!\n”);
flag = 0;
printf(“Wait for thread to exit\n”);
pthread_join(thread, NULL);
printf(“Bye\n”);
return 0;
}
輸入q後,需要等線程從sleep中醒來(由掛起狀態變為運行狀態),即最壞情況要等10s,線程才會被join。采用sleep的缺點:不能及時喚醒線程。
采用pthread_cond_timedwait函數實現的如下
[cpp] view
plain copy
include <stdio.h>
include <sys/time.h>
include <unistd.h>
include <pthread.h>
include <errno.h>
pthread_t thread;
pthread_cond_t cond;
pthread_mutex_t mutex;
unsigned char flag = 1;
void * thr_fn(void * arg)
{
struct timeval now;
struct timespec outtime;
pthread_mutex_lock(&mutex);
while (flag)
{
printf(“thread sleep now\n”);
gettimeofday(&now, NULL);
outtime.tv_sec = now.tv_sec + 10;
outtime.tv_nsec = now.tv_usec * 1000;
pthread_cond_timedwait(&cond, &mutex, &outtime);
}
pthread_mutex_unlock(&mutex);
printf(“thread exit\n”);
}
int main()
{
char c ;
pthread_mutex_init(&mutex, NULL);
pthread_cond_init(&cond, NULL);
if (0 != pthread_create(&thread, NULL, thr_fn, NULL))
{
printf(“error when create pthread,%d\n”, errno);
return 1;
}
while ((c = getchar()) != ‘q’);
printf(“Now terminate the thread!\n”);
flag = 0;
pthread_mutex_lock(&mutex);
pthread_cond_signal(&cond);
pthread_mutex_unlock(&mutex);
printf(“Wait for thread to exit\n”);
pthread_join(thread, NULL);
printf(“Bye\n”);
return 0;
}
條件變量是 GNU/Linux 提供的第三種同步工具(第一互斥體第二這信號量);利用它你可以在多線程環境下實現更復雜的條件控制。
當標志沒有被設置的時候,線程會不斷循環檢測這個標志,同時會不斷鎖定、解鎖互斥體,浪費 CPU 時間。你真正需要的是這樣一種方法:當標志沒有設置的時候讓線程進入休眠狀態;而當某種特定條件出現時,標志位被設置,線程被喚醒。
如同信號量,線程可以對一個條件變量執行等待操作。如果如果線程 A 正在等待一個條件變量,它會被阻塞直到另外一個線程B,向同一個條件變量發送信號以改變其狀態。不同於信號量,條件變量沒有計數值,也不占據內存空間,線程 A 必須在 B 發送信號之前開始等待。如果 B
在 A 執行等待操作之前發送了信號,這個信號就丟失了,同時 A會一直阻塞直到其它線程再次發送信號到這個條件變量。
條件變量將允許你實現這樣的目的:在一種情況下令線程繼續運行,而相反情況下令線程阻塞。只要每個可能涉及到改變狀態的線程正確使用條件變量,Linux 將保證當條件改變的時候由於一個條件變量的狀態被阻塞的線程均能夠被激活。
GNU/Linux 剛好提供了這個機制,每個條件變量都必須與一個互斥體共同使用,以防止這種競爭狀態的發生。這種設計下,線程函數應遵循以下步驟:
thread_function中的循環首先鎖定互斥體並且讀取標志變量的值。
如果標志變量已經被設定,該線程將互斥體解鎖然後執行工作函數
如果標志沒有被設置,該線程自動鎖定互斥體並開始等待條件變量的信號
這裡最關鍵的特點就在第三條。這裡,GNU/Linux系統允許你用一個原子操作完成解除互斥體鎖定和等待條件變量信號的過程而不會被其它線程在中途插入執行。這就避免了在thread_function中檢測標志和等待條件變量的過程中其它線程修改標志變量並對條件變量發送信號的可能性。
pthread_cond_t pCond;
pthread_cond_init(&pCond,NULL); 第一個參數是一個指向pthread_cond_t變量的指針。第二個參數是一個指向條件變量屬性對象的指針;這個參數在 GNU/Linux 系統中是被忽略的。
pthread_cond_signal(&pCond)如果沒有線程正在等待這個信號,則這個信號會被忽略。該函數的
參數是一個指向 pthread_cond_t 類型變量的指針。
pthread_cond_broadcast()函數會將所有等待該條件變量的線程解鎖而不是僅僅解鎖一個線程
pthread_cond_wait(&pCond,&mutex)會讓調用線程阻塞直到條件變量收到信號。第一個參數是指向一個 pthread_cond_t 類型變量的指針,第二個參數是指向一個pthread_mutex_t類型變量的指針。當調用 pthread_cond_wait 的時候,互斥體對象必須已經被調用線程鎖定。這個函數以一個原子操作解鎖互斥體並鎖定條件變量等待信號。當信號到達且調用線程被解鎖之後,pthread_cond_wait自動申請鎖定互斥體對象。
pthread_mutex_lock(&qlock);
pthread_cond_wait(&qready, &qlock); //其它線程pthread_cond_sigal發出信號才會對出阻塞
pthread_mutex_unlock(&qlock);
The mutex passed to pthread_cond_wait protects the condition.The caller passes it locked to the function, which then atomically places the calling thread on the list of threads waiting
for thecondition 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.
上面是APUE的原話,就是說pthread_cond_wait(pthread_cond_t *cond, pthread_mutex_t*mutex)
函數傳入的參數mutex用於保護條件,因為我們在調用pthread_cond_wait時,如果條件不成立我們就進入阻塞,但是進入阻塞這個期間,如果條件變量改變了的話,那我們就漏掉了這個條件。因為這個線程還沒有放到等待隊列上,所以調用pthread_cond_wait前要先鎖互斥量,即調用pthread_mutex_lock(),pthread_cond_wait在把線程放進阻塞隊列後,自動對mutex進行解鎖,使得其它線程可以獲得加鎖的權利。這樣其它線程才能對臨界資源進行訪問並在適當的時候喚醒這個阻塞的進程。當pthread_cond_wait返回的時候又自動給mutex加鎖
實際上邊代碼的加解鎖過程如下:
pthread_mutex_lock(&qlock);
pthread_cond_wait(&qready, &qlock);
pthread_mutex_unlock(&qlock);
上文來自:http://blog.csdn.net/cupidove/article/details/9331859
一個簡單的實例程序,說明pthread_cond_wait 和 pthread_cond_broadcast 的使用方式。
函數定義:
int pthread_cond_wait(pthread_cond_t *cond, pthread_mutex_t *mutex)
int pthread_cond_broadcast(pthread_cond_t *cond)
函數說明:
pthread_cond_wait :有兩個輸入參數,一個是pthread_cond_t,是函數將要等待的信號,另一個是 pthread_mutex_t,一個互斥鎖。用於對信號量進行保護,防止多個線程同時對其進行操作。在線程開始等待信號量前,必須由本線程對互斥鎖進行鎖定,然後pthread_cond_wait會更新條件等待隊列,並且釋放互斥量,允許其他線程進行訪問;當cond 滿足條件允許線程繼續執行時,wait_cond也會先對mutex 進行鎖定,對cond進行處理,然後再允許線程繼續運行。所以pthread_cond_wait()
後的pthread_mutex_unlock()還是必要的。

實例程序:
[cpp] view
plain copy





#include <pthread.h>
#include <iostream>
#include <unistd.h>
using namespace std;
static pthread_mutex_t mtx=PTHREAD_MUTEX_INITIALIZER;
static pthread_cond_t cond=PTHREAD_COND_INITIALIZER;
static void* func_1(void* arg)
{
cout << "func_1 start" << endl;
pthread_mutex_lock(&mtx);
cout << "func_1 lock mtx" << endl;
cout << "func_1 wait cond" << endl;
pthread_cond_wait(&cond, &mtx);
cout << "func_1 unlock mtx" << endl;
pthread_mutex_unlock(&mtx);
cout << "func_1 end" << endl;
sleep(5);
return NULL;
}
static void* func_2(void* arg)
{
cout << "func_2 start" << endl;
pthread_mutex_lock(&mtx);
cout << "func_2 lock mtx" << endl;
cout << "func_2 wait cond" << endl;
pthread_cond_wait(&cond, &mtx);
cout << "func_2 unlock mtx" << endl;
pthread_mutex_unlock(&mtx);
cout << "func_2 end" << endl;
sleep(5);
return NULL;
}
int main()
{
pthread_t tid1, tid2;
cout << "main create thread" << endl;
pthread_create(&tid1, NULL, func_1, NULL);
pthread_create(&tid2, NULL, func_2, NULL);
sleep(3);
cout << "main boradcast signal" << endl;
pthread_cond_broadcast(&cond);
cout << "main join thread" << endl;
pthread_join(tid1, NULL);
pthread_join(tid2, NULL);
cout << "main end" << endl;
return 0;
}
測試結果:

上文來自:http://blog.csdn.net/wangzhiyu1980/article/details/44227913
編寫一個程序,開啟3個線程,這3個線程的ID分別為A、B、C,每個線程將自己的ID在屏幕上打印10遍,要求輸出結果必須按ABC的順序顯示;如:ABCABC….依次遞推
編寫一個程序,開啟3個線程,這3個線程的ID分別為A、B、C,每個線程將自己的ID在屏幕上打印10遍,要求輸出結果必須按ABC的順序顯示;如:ABCABC….依次遞推。
好長時間沒有再想寫代碼了,雖然自己還沒有畢業,處於學習的階段,但是很少是主動的寫過多少,代碼量太少是一大障礙。在不久就面臨畢業找工作,剛才看了許久的各大公司的筆試題,看懂的沒有幾道,會的更少。自己弱爆了,怎麼辦。在這裡,我把自己會的盡量寫,借此激勵自己。
老師講的這是迅雷的筆試題: 是不是無關緊要,主要是上次考試的時候這就是最後一道題,要求用手寫確實不容易.
題意很明了,要求也很簡單,自己傻逼一樣一看就笑了,用一個sleep()愉快的完成了這道題,感覺還很牛B..下面是當時自己在試卷上的作答:
[c] view
plain copy
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<errno.h>
#include<pthread.h>
#include<unistd.h>
void *th_fun(void* arg){
int i=0;
while(i < 10){
printf("the num is:%lx\n",pthread_self());
i++;
usleep(150);
}
return ((void *)0);
}
int main(void){
pthread_t th1,th2,th3;
//參數的類型: int*
if(0 != pthread_create(&th1,NULL,th_fun,NULL)){
fprintf(stderr,"pthread %s\n",strerror(errno));
exit(1);
}
usleep(50);
if(0 != pthread_create(&th2,NULL,th_fun,NULL)){
fprintf(stderr,"pthread %s\n",strerror(errno));
exit(1);
}
usleep(50);
if(0 != pthread_create(&th3,NULL,th_fun,NULL)){
fprintf(stderr,"pthread %s\n",strerror(errno));
exit(1);
}
pthread_join(th1,NULL);
pthread_join(th2,NULL);
pthread_join(th3,NULL);
return 0;
}
</unistd></pthread></errno></string></stdlib></stdio>
結果是把每個線程的編號打印三遍,但是用sleep確實沒有什麼意思,所以這麼做只能得0分。創建線程的時候用了usleep(50)不然打印出結果就是錯的,sleep本身就不精確。沒多少線程控制的含量,沒有用到互斥鎖和條件變量。
假設有三個線程A, B, C;A線程首先執行,B線程等待A結束後執行,C線程等待B結束後執行,A線程又要等待C線程結束後執行,B再等待A,C再等待B....以此類推,是一個循環等待的過程,每一個線程要做的事情:1.搶到鎖,設置標志位為1(告訴上家自己在等待信號);2.收到上家的信號,立即設置標志為為0,並打印出自己的線程號;3.確定下家是否在等待,確定下家在等待後,立即發送信號給下家,再打開鎖,usleep(20)(讓其他線程搶到鎖)。
其中有兩個要注意的地方:1.三個線程創建好後,三個線程都在死等待 [A等C,B等A,C等B] 所以首先手動代替C為A發送信號,讓程序執行。2.A線程的10次循環結束後,flag標志位是0,而此時C線程還沒有執行完畢,C要檢查A的標志為是否為1再給A發送信號,所以在A循環結束後把它的flag標志為置為1。
看程序:
[c] view
plain copy
#include<stdio.h>
#include<errno.h>
#include<string.h>
#include<stdlib.h>
#include<pthread.h>
#define PRINTTIME 10
/*互斥鎖 MUTEX*/
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
/*條件變量*/
pthread_cond_t condA_B = PTHREAD_COND_INITIALIZER;
pthread_cond_t condB_C = PTHREAD_COND_INITIALIZER;
pthread_cond_t condC_A = PTHREAD_COND_INITIALIZER;
int flagA = 0,flagB = 0,flagC = 0;
void *th_A_C(void *arg){
printf("A come!\n");
int i = 0;
char *name = (char *)arg;
while(i < PRINTTIME){
pthread_mutex_lock(&mutex);
//printf("A LOCKED\n");
flagA = 1;
/*等待C的信號*/
pthread_cond_wait(&condC_A,&mutex);
flagA = 0;
printf("%c:%d-->%lx\n",*name,i,pthread_self());
/*發信號給B*/
/*在發信號給B之前,先檢測B有沒有在等待*/
/*若B在等待,在這裡就可以檢測到標志位flagB == 1*/
while(!flagB){
pthread_mutex_unlock(&mutex);
usleep(30);
// printf("--------------------------wait flagB\n");
pthread_mutex_lock(&mutex);
}/*循環結束表示flagBC為1,就是B已經加鎖,並在等待A給它信號,所以現在A發信號給B*/
// printf("signal A--->B finished!\n");
pthread_cond_signal(&condA_B);
pthread_mutex_unlock(&mutex);
// printf("%c UNLOCK!\n",*name);
i++;
usleep(20);
}
/*A的循環結束的時候把自己的flagA 位置為1,欺騙C線程 讓C線程以為A這邊准備好了,然後發信號給他。這樣可以避免C判斷A沒有再等帶它的標志一直死循環狀態退不出來*/
flagA = 1;
}
void *th_B_A(void *arg){
printf("B come!\n");
int i = 0;
char *name = (char *)arg;
while(i < PRINTTIME){
pthread_mutex_lock(&mutex);
// printf("B LOCKED\n");
/*B搶到鎖,設置標志位flagBC = 1*/
flagB = 1;
/*等待A的信號*/
pthread_cond_wait(&condA_B,&mutex);
flagB = 0;
printf("%c:%d-->%lx\n",*name,i,pthread_self());
/*發信號給C*/
/*在發信號給C之前先檢測C有沒有在等待*/
/*若C在等待則flagC == 1*/
while(!flagC){
pthread_mutex_unlock(&mutex);
usleep(30);
// printf("--------------------------wait flagC\n");
pthread_mutex_lock(&mutex);
}
/*循環結束表示flagC 已經為1 ,所以開始給C發信號*/
// printf("signal B--->C finished!\n");
pthread_cond_signal(&condB_C);
pthread_mutex_unlock(&mutex);
// printf("%c UNLOCK!\n",*name);
i++;
usleep(20);
}
}
void *th_C_B(void *arg){
printf("C come!\n");
int i = 0;
char *name = (char *)arg;
while(i < PRINTTIME){
pthread_mutex_lock(&mutex);
// printf("C LOCKED\n");
flagC = 1;
/*等待B的信號*/
pthread_cond_wait(&condB_C,&mutex);
flagC = 0;
printf("%c:%d-->%lx\n",*name,i,pthread_self());
/*發信號給A*/
/*發信號給A 之前先檢測A有沒有在等待,若在等待 則flagA == 1*/
while(!flagA){
pthread_mutex_unlock(&mutex);
usleep(30);
// printf("--------------------------wait flagA\n");
pthread_mutex_lock(&mutex);
}
/*循環結束表示A在等待,所以發信號給A*/
// printf("signal C--->A finished!\n");
pthread_cond_signal(&condC_A);
pthread_mutex_unlock(&mutex);
// printf("%c UNLOCK!\n",*name);
i++;
usleep(20);
}
}
int main(void){
pthread_t th1,th2,th3;
char name1 = 'A',name2 = 'B',name3 = 'C';
int *p1 =(int *) &name1;
int *p2 =(int *) &name2;
int *p3 =(int *) &name3;
if(pthread_create(&th1,NULL,th_A_C,(void *)p1) < 0){
fprintf(stderr,"pthread_create th1 %s\n",strerror(errno));
exit(1);
}
usleep(30);
if(pthread_create(&th2,NULL,th_B_A,(void *)p2) < 0){
fprintf(stderr,"pthread_create th2 %s\n",strerror(errno));
exit(1);
}
usleep(30);
if(pthread_create(&th3,NULL,th_C_B,(void *)p3) < 0){
fprintf(stderr,"pthread_create th1 %s\n",strerror(errno));
exit(1);
}
//起始給線程A發通知,防止A,b,c,死鎖
/*直接通知A,不能內個讓他再傻等*/
pthread_cond_broadcast(&condC_A);
pthread_join(th1,NULL);
printf("th1 finished!\n");
pthread_join(th2,NULL);
printf("th2 finished!\n");
pthread_join(th3,NULL);
printf("th3 finished!\n");
return 0;
}
</pthread></stdlib></string></errno></stdio>
程序順利執行,結果正確。但是代碼冗余很大,可擴展性不好,在下面做改進。。

改進版的, 把A,B,C先程中的大量重復部分封裝成一個函數,用循環創建和回收線程。
[c] view
plain copy
#include<stdio.h>
#include<errno.h>
#include<string.h>
#include<stdlib.h>
#include<pthread.h>
#define PRINTTIME 10
/*互斥鎖 MUTEX*/
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
/*條件變量*/
pthread_cond_t condA_B = PTHREAD_COND_INITIALIZER;
pthread_cond_t condB_C = PTHREAD_COND_INITIALIZER;
pthread_cond_t condC_A = PTHREAD_COND_INITIALIZER;
int flagA = 0,flagB = 0,flagC = 0;
void pthread_print(pthread_cond_t *cond_wait,char *name,int *flag_self,int *flag_wait,pthread_cond_t *cond_signal){
printf("%c come!\n",*name);
int i = 0;
while(i < PRINTTIME){
pthread_mutex_lock(&mutex);
*flag_self = 1;
pthread_cond_wait(cond_wait,&mutex);
*flag_self = 0;
printf("%c:%d-->%lx\n",*name,i,pthread_self());
while(!(*flag_wait)){
pthread_mutex_unlock(&mutex);
usleep(30);
pthread_mutex_lock(&mutex);
}/*循環結束表示flagBC為1,就是B已經加鎖,並在等待A給它信號,所以現在A發信號給B*/
pthread_cond_signal(cond_signal);
pthread_mutex_unlock(&mutex);
i++;
usleep(20);
}
}
void *th_A_C(void *arg){
char *name = (char *)arg;
pthread_print(&condC_A,name,&flagA,&flagB,&condA_B);
flagA = 1;/*防止C 等待 A 而不能結束*/
}
void *th_B_A(void *arg){
char *name = (char *)arg;
pthread_print(&condA_B,name,&flagB,&flagC,&condB_C);
}
void *th_C_B(void *arg){
char *name = (char *)arg;
pthread_print(&condB_C,name,&flagC,&flagA,&condC_A);
}
int main(void){
char name1 = 'A',name2 = 'B',name3 = 'C';
char *p[] = {
(char *) &name1,
(char *) &name2,
(char *) &name3
};
void *(*th_funs[])(void *) = {
th_A_C,
th_B_A,
th_C_B
};
int count = sizeof(th_funs)/sizeof(th_funs[0]);
pthread_t th[count];
int i = 0;
while(i < count){
if(pthread_create(&th[i],NULL,th_funs[i],(void *)p[i]) < 0){
fprintf(stderr,"pthread_create th1 %s\n",strerror(errno));
exit(1);
}
usleep(30);
i++;
}
pthread_cond_broadcast(&condC_A);
for(i = 0;i < count;i++){
pthread_join(th[i],NULL);
printf("th%d finished!\n",i);
}
return 0;
}
</pthread></stdlib></string></errno></stdio>
上一個封裝的不好,最後一個版本老師給的,封裝的更好一些:
[c] view
plain copy
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <pthread.h>
#define LP_TIMES 10
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t cond_AB = PTHREAD_COND_INITIALIZER;
pthread_cond_t cond_BC = PTHREAD_COND_INITIALIZER;
pthread_cond_t cond_CA = PTHREAD_COND_INITIALIZER;
//標記
int flag_AB,flag_BC,flag_CA;
//標記檢查的線程等待
void th_condflag_wait(int *flag,pthread_cond_t *cond,pthread_mutex_t *mutex)
{
(*flag) = 1;
pthread_cond_wait(cond,mutex);
(*flag) = 0;
}
//標記檢查的線程通知
void th_condflag_broadcast(int *flag,pthread_cond_t *cond,pthread_mutex_t *mutex)
{
while(!(*flag))
{
pthread_mutex_unlock(mutex);
usleep(50);
pthread_mutex_lock(mutex);
}
pthread_cond_broadcast(cond);
}
void *th_fun_A(void *arg)
{
int i = LP_TIMES;
while(i--)
{
pthread_mutex_lock(&mutex);
//A wait C
th_condflag_wait(&flag_CA,&cond_CA,&mutex);
printf("A%d: %lx\n",10-i,pthread_self());
//A cond B
th_condflag_broadcast(&flag_AB,&cond_AB,&mutex);
pthread_mutex_unlock(&mutex);
usleep(50);
}
//防止C線程最後一次等待A線程時死鎖
flag_CA = 1;
}
void *th_fun_B(void *arg)
{
int i = LP_TIMES;
while(i--)
{
pthread_mutex_lock(&mutex);
//B wait A
th_condflag_wait(&flag_AB,&cond_AB,&mutex);
printf("B%d: %lx\n",10-i,pthread_self());
//B cond C
th_condflag_broadcast(&flag_BC,&cond_BC,&mutex);
pthread_mutex_unlock(&mutex);
usleep(50);
}
}
void *th_fun_C(void *arg)
{
int i = LP_TIMES;
while(i--)
{
pthread_mutex_lock(&mutex);
//C wait B
th_condflag_wait(&flag_BC,&cond_BC,&mutex);
printf("C%d: %lx\n",10-i,pthread_self());
//C cond A
th_condflag_broadcast(&flag_CA,&cond_CA,&mutex);
pthread_mutex_unlock(&mutex);
usleep(50);
}
}
int main(void)
{
printf("main: %lx\n",pthread_self());
//保存3個線程的處理函數
void *(*th_funs[])(void *) =
{
th_fun_A,
th_fun_B,
th_fun_C
};
int th_count = sizeof(th_funs)/sizeof(th_funs[0]);
pthread_t th[th_count];
int i;
for(i = 0;i < th_count;i++)
{
//通過線程函數數組記錄的函數來創建線程
if(pthread_create(th+i,NULL,th_funs[i],(void *)i) < 0)
{
fprintf(stderr,"th_create: %s\n",
strerror(errno));
exit(1);
}
printf("th[%d]: %lx\n",i,th[i]);
}
//起始給A線程發出通知,防止A和C死鎖
pthread_mutex_lock(&mutex);
th_condflag_broadcast(&flag_CA,&cond_CA,&mutex);
pthread_mutex_unlock(&mutex);
//回收線程
for(i = 0;i < th_count;i++)
{
pthread_join(th[i],NULL);
printf("i: %d finished!\n",i);
}
return 0;
}
</pthread></errno></string></stdlib></stdio>
上文來自:/content/993274.html
Copyright © Linux教程網 All Rights Reserved