http://www.cnblogs.com/yuuyuu/p/5152560.html
一.概述 ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ??
barrier(屏障)與互斥量,讀寫鎖,自旋鎖不同,它不是用來保護臨界區的。相反,它跟條件變量一樣,是用來協同多線程一起工作!!!
條件變量是多線程間傳遞狀態的改變來達到協同工作的效果。屏障是多線程各自做自己的工作,如果某一線程完成了工作,就等待在屏障那里,直到其他線程的工作都完成了,再一起做別的事。舉個通俗的例子:
1.對于條件變量。在接力賽跑里,1號隊員開始跑的時候,2,3,4號隊員都站著不動,直到1號隊員跑完一圈,把接力棒給2號隊員,2號隊員收到接力棒后就可以跑了,跑完再給3號隊員。這里這個接力棒就相當于條件變量,條件滿足后就可以由下一個隊員(線程)跑。
2.對于屏障。在百米賽跑里,比賽沒開始之前,每個運動員都在賽場上自由活動,有的熱身,有的喝水,有的跟教練談論。比賽快開始時,準備完畢的運動員就預備在起跑線上,如果有個運動員還沒準備完(除去特殊情況),他們就一直等,直到運動員都在起跑線上,裁判喊口號后再開始跑。這里的起跑線就是屏障,做完準備工作的運動員都等在起跑線,直到其他運動員也把準備工作做完!
二.函數接口 ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ??
1.創建屏障
1 #include <pthread.h> 2 3 int pthread_barrier_init(pthread_barrier_t *restrict barrier, const pthread_barrierattr_t *restrict attr, unsigned count);
barrier:pthread_barrier_t結構體指針
attr:屏障屬性結構體指針
count:屏障等待的線程數目,即要count個線程都到達屏障時,屏障才解除,線程就可以繼續執行
2.等待
1 #include <pthread.h> 2 3 int pthread_barrier_wait(pthread_barrier_t *barrier);
函數的成功返回值有2個,第一個成功返回的線程會返回PTHREAD_BARRIER_SERIAL_THREAD,其他線程都返回0。可以用第一個成功返回的線程來做一些善后處理工作。
3.銷毀屏障
1 #include <pthread.h> 2 3 int pthread_barrier_destroy(pthread_barrier_t *barrier);
三.簡單例子 ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ??
寫個簡單的例子,主線程等待其他線程都完成工作后自己再向下執行,類似pthread_join()函數!
1 /** 2 * @file pthread_barrier.c 3 */ 4 5 #include <stdio.h> 6 #include <stdlib.h> 7 #include <string.h> 8 #include <unistd.h> 9 #include <pthread.h> 10 11 /* 屏障總數 */ 12 #define PTHREAD_BARRIER_SIZE 4 13 14 /* 定義屏障 */ 15 pthread_barrier_t barrier; 16 17 void err_exit(const char *err_msg) 18 { 19 printf("error:%s\n", err_msg); 20 exit(1); 21 } 22 23 void *thread_fun(void *arg) 24 { 25 int result; 26 char *thr_name = (char *)arg; 27 28 /* something work */ 29 30 printf("線程%s工作完成...\n", thr_name); 31 32 /* 等待屏障 */ 33 result = pthread_barrier_wait(&barrier); 34 if (result == PTHREAD_BARRIER_SERIAL_THREAD) 35 printf("線程%s,wait后第一個返回\n", thr_name); 36 else if (result == 0) 37 printf("線程%s,wait后返回為0\n", thr_name); 38 39 return NULL; 40 } 41 42 int main(void) 43 { 44 pthread_t tid_1, tid_2, tid_3; 45 46 /* 初始化屏障 */ 47 pthread_barrier_init(&barrier, NULL, PTHREAD_BARRIER_SIZE); 48 49 if (pthread_create(&tid_1, NULL, thread_fun, "1") != 0) 50 err_exit("create thread 1"); 51 52 if (pthread_create(&tid_2, NULL, thread_fun, "2") != 0) 53 err_exit("create thread 2"); 54 55 if (pthread_create(&tid_3, NULL, thread_fun, "3") != 0) 56 err_exit("create thread 3"); 57 58 /* 主線程等待工作完成 */ 59 pthread_barrier_wait(&barrier); 60 printf("所有線程工作已完成...\n"); 61 62 sleep(1); 63 return 0; 64 }
28行是線程自己要做的工作,62行的sleep(1)讓所有線程有足夠的時間把自己的返回值打印出來。編譯運行:
可以看到,3個線程工作完成后才可以越過屏障打印返回值,第一個返回的是PTHREAD_BARRIER_SERIAL_THREAD,其他都是0。
這里有一點要注意:我們從運行結果看出,主線程打印"所有線程工作已完成"之后,線程1,線程2還在運行打印返回值。這個結果難免會誤解"主線程等待所有線程完成工作之后再向下執行"。區分一點即可:等待只針對屏障之前的動作,越過屏障后,無論是主線程,還是子線程都會并發執行,如果非要讓子線程完完全全執行完,可以再加個屏障到線程函數末尾,相應主線程也要加!