如何使用pthread_barrier_xxx系列函数来实现多线程之间的同步?

描述

在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);
}

 

程序的运行结果如下图所示:

Linux系统







审核编辑:刘清

打开APP阅读更多精彩内容
声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉

全部0条评论

快来发表一下你的评论吧 !

×
20
完善资料,
赚取积分