pthread使用barrier栅栏方式同步
Linux中提供了多种同步机制,其中使用barrier(栅栏)是多线程之间进行同步的方法之一。
基本原理:
假设多个线程约定一个栅栏,只有当所有的线程都达到这个栅栏时,栅栏才会放行,否则到达此处的线程将被阻塞。
使用场景:
程序启动的时候,需要建立一个独立的线程去做一些特殊的工作。比如这个线程需要初始化一些全局配置等等。而主线程启动后,必须等待这个子线程拿到配置信息后,才能继续工作。所以这里就存在一个问题要解决,主线程如何等待这个子线程完成工作后,才继续往下执行呢?
栅栏相关API
#include <pthread.h> //初始化栅栏,栅栏需要等待到count个线程,才会全部一起放行。 int pthread_barrier_init(pthread_barrier_t *restrict, const pthread_barrierattr_t *restrict, unsigned count); //报道函数,当一个线程到达栅栏的时候,就报道。 //所有的线程都报道后,栅栏自然会放行。 int pthread_barrier_wait(pthread_barrier_t *barrier); 栅栏完成历史使命后,当然是功成身退。 int pthread_barrier_destroy(pthread_barrier_t *barrier);
使用示例
#include <stdio.h> #include <time.h> #include <stdlib.h> #include <string.h> #include <pthread.h> #include <unistd.h> pthread_barrier_t barrier; void* initor(void* args) { printf("---------------thread init work(%d)-------------- ", time(NULL)); //模拟初始化工作。 sleep(10); //到达栅栏 pthread_barrier_wait(&barrier); printf("--------------thread start work(%d)-------------- ", time(NULL)); sleep(10); printf("--------------thread stop work(%d)-------------- ", time(NULL)); return NULL; } int main(int argc, char* argv[]) { //初始化栅栏,该栅栏等待两个线程到达时放行 pthread_barrier_init(&barrier, NULL, 2); printf("**************main thread barrier init done**************** "); pthread_t pid; pthread_create(&pid, NULL, &initor, NULL); printf("**************main waiting(%d)******************** ", time(NULL)); //主线程到达,被阻塞,当初始化线程到达栅栏时才放行。 pthread_barrier_wait(&barrier); pthread_barrier_destroy(&barrier); printf("***************main start to work(%d)**************** ", time(NULL)); sleep(30); pthread_join(pid, NULL); printf("***************thread complete(%d)*************** ", time(NULL)); return 0; }
root@ubuntu:/data1# gcc test.c -lpthread -o test root@ubuntu:/data1# ./test **************main thread barrier init done**************** **************main waiting(1615809746)******************** ---------------thread init work(1615809746)-------------- --------------thread start work(1615809756)-------------- ***************main start to work(1615809756)**************** --------------thread stop work(1615809766)-------------- ***************thread complete(1615809786)*************** root@ubuntu:/data1#
#include <stdio.h> #include <pthread.h> #define THREAD_NUMS 4 pthread_barrier_t barrier; void *t0(void *param) { pthread_barrier_wait(&barrier); printf("t0 ready "); } void *t1(void *param) { pthread_barrier_wait(&barrier); printf("t1 ready "); } void *t2(void *param) { pthread_barrier_wait(&barrier); printf("t2 ready "); } int main(void) { pthread_t t[3]; pthread_barrier_init(&barrier, NULL, THREAD_NUMS); #include <stdio.h> #include <pthread.h> #define THREAD_NUMS 4 pthread_barrier_t barrier; void *t0(void *param) { pthread_barrier_wait(&barrier); printf("t0 ready "); } void *t1(void *param) { pthread_barrier_wait(&barrier); printf("t1 ready "); } void *t2(void *param) { pthread_barrier_wait(&barrier); printf("t2 ready "); } int main(void) { pthread_t t[3]; pthread_barrier_init(&barrier, NULL, THREAD_NUMS); pthread_create(&t[0], NULL, t0, NULL); pthread_create(&t[1], NULL, t1, NULL); pthread_create(&t[2], NULL, t2, NULL); pthread_barrier_wait(&barrier); printf("all sub threads ready, go! "); pthread_barrier_destroy(&barrier); } pthread_create(&t[0], NULL, t0, NULL); pthread_create(&t[1], NULL, t1, NULL); pthread_create(&t[2], NULL, t2, NULL); pthread_barrier_wait(&barrier); printf("all sub threads ready, go! "); pthread_barrier_destroy(&barrier); }
root@ubuntu:/data1# gcc barrier.c -lpthread -o barrier root@ubuntu:/data1# ./barrier t0 ready t2 ready t1 ready all sub threads ready, go!