在Linux系统中提供了多种同步机制,本文主要讲讲如何使用pthread_barrier_xxx系列函数来实现多线程之间进行同步的方法。
函数定义
pthread_barrier_xxx系列函数中的barrier可意为栅栏,可以理解为该栅栏能够把先后到达的多个线程阻挡在同一栅栏前,直到所有线程到齐,栅栏才会放行,否则到达此处的线程将被阻塞。
pthread_barrier_xxx系列函数在
// 初始化栅栏,负责指定栅栏要等待的线程个数, // 栅栏需要等待count个线程都到达栅栏时,才会全部一起放行 int pthread_barrier_init(pthread_barrier_t *restrict, const pthread_barrierattr_t *restrict, unsigned count); // pthread_barrier_wait()函数会同步所有参与barrier的线程, // 调用该函数的线程会阻塞住,直到pthread_barrier_init()中指定 // 数量的线程调用了pthread_barrier_wait()函数,所有线程才会同时往下执行 int pthread_barrier_wait(pthread_barrier_t *barrier); // 释放pthread_barrier_init()函数申请的资源 int pthread_barrier_destroy(pthread_barrier_t *barrier);
应用场景
在应用程序启动的时候,需要创建一个或者多个线程去完成不同功能的处理。子线程启动之后,需要等待主进程完成基础的配置之后各个子线程才能正常工作。所以这里就存在一个问题要解决,各个子线程如何等待主进程完成工作后,才继续往下执行呢?
为了解决上述场景的问题,我们可以在调用pthread_barrier_init()时指定n+1个等待,其中n是线程数。而在每个线程执行函数的开始调用pthread_barrier_wait()。这样主进程在调用pthread_create()创建子线程后,子线程运行到pthread_barrier_wait()后将被阻塞,线程都停下来等待最后一个pthread_barrier_wait()函数被调用。最后一个pthread_barrier_wait()函数由主进程或者其他子线程在它觉得合适的时候调用就行。最后这个pthread_barrier_wait()有点像跑步运动时的起步枪,只有最后这个pthread_barrier_wait()函数被调用,其他被阻塞的线程就能够继续运行。
使用实例
下面的程序,在main()函数中,pthread_barrier_init()指定2+1个等待,接着创建了2个线程,然后主进程延时6秒,之后调用pthread_barrier_wait()来让线程接着运行,程序如下:
/* ******************************************************************************** *描述:pthread_barrier_xxx程序示例 *Use:gcc pthread_barrier_xxx.c -lpthread * ./a.out *By:Ailson Jack *Date:2016.03.24 *CSDN//blog.csdn.net/jackailson ******************************************************************************** */ #include#include #include #include // 线程栅栏 pthread_barrier_t barrier; void *task1(void *arg); void *task2(void *arg); int main(void) { pthread_t task1_tid; pthread_t task2_tid; pthread_attr_t task1_attr; pthread_attr_t task2_attr; // 初始化线程属性 pthread_attr_init(&task1_attr); pthread_attr_init(&task2_attr); // 初始化栅栏 pthread_barrier_init(&barrier, NULL, 2+1); // 2+1 个等待 // 创建线程1 pthread_create(&task1_tid, &task1_attr, task1, NULL); // 创建线程2 pthread_create(&task2_tid, &task2_attr, task2, NULL); printf("main process will sleep 6s. "); sleep(6); // 等待6s,让task1和task2都阻塞住了,再运行主线程 // 主线程调用pthread_barrier_wait()函数之后,已经达到了 // pthread_barrier_init()函数设置的3个等待条件,此时调用 // pthread_barrier_wait()函数的主线程不会被阻塞,task1和 // task2也将继续运行. pthread_barrier_wait(&barrier); pthread_join(task1_tid, NULL); pthread_join(task2_tid, NULL); pthread_barrier_destroy(&barrier); } void *task1(void *arg) { printf("task1 will be blocked. "); pthread_barrier_wait(&barrier); // 线程将被阻塞在这里 printf("task1 is running. "); sleep(3); // 延时3s pthread_exit(NULL); } void *task2(void *arg) { printf("task2 will be blocked. "); pthread_barrier_wait(&barrier); // 线程将被阻塞在这里 printf("task2 is running. "); sleep(3); // 延时3s pthread_exit(NULL); }
程序的运行结果如下图所示:
审核编辑:刘清
全部0条评论
快来发表一下你的评论吧 !