一.概述                                                   

barrier(屏障)与互斥量读写锁自旋锁不同,它不是用来保护临界区的。相反,它跟条件变量一样,是用来协同多线程一起工作!!!

条件变量是多线程间传递状态的改变来达到协同工作的效果。屏障是多线程各自做自己的工作,如果某一线程完成了工作,就等待在屏障那里,直到其他线程的工作都完成了,再一起做别的事。举个通俗的例子:

1.对于条件变量。在接力赛跑里,1号队员开始跑的时候,2,3,4号队员都站着不动,直到1号队员跑完一圈,把接力棒给2号队员,2号队员收到接力棒后就可以跑了,跑完再给3号队员。这里这个接力棒就相当于条件变量,条件满足后就可以由下一个队员(线程)跑。

2.对于屏障。在百米赛跑里,比赛没开始之前,每个运动员都在赛场上自由活动,有的热身,有的喝水,有的跟教练谈论。比赛快开始时,准备完毕的运动员就预备在起跑线上,如果有个运动员还没准备完(除去特殊情况),他们就一直等,直到运动员都在起跑线上,裁判喊口号后再开始跑。这里的起跑线就是屏障,做完准备工作的运动员都等在起跑线,直到其他运动员也把准备工作做完!

二.函数接口                                           

1.创建屏障

 #include <pthread.h>

 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.等待

 #include <pthread.h>

 int pthread_barrier_wait(pthread_barrier_t *barrier);

函数的成功返回值有2个,第一个成功返回的线程会返回PTHREAD_BARRIER_SERIAL_THREAD,其他线程都返回0。可以用第一个成功返回的线程来做一些善后处理工作。

3.销毁屏障

 #include <pthread.h>

 int pthread_barrier_destroy(pthread_barrier_t *barrier);

三.简单例子                                           

写个简单的例子,主线程等待其他线程都完成工作后自己再向下执行,类似pthread_join()函数!

 /**
  * @file pthread_barrier.c
  */

 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
 #include <unistd.h>
 #include <pthread.h>

 /* 屏障总数 */
 #define PTHREAD_BARRIER_SIZE 4

 /* 定义屏障 */
 pthread_barrier_t barrier;

 void err_exit(const char *err_msg)
 {
     printf("error:%s\n", err_msg);
     exit();
 }

 void *thread_fun(void *arg)
 {
     int result;
     char *thr_name = (char *)arg;

     /* something work */

     printf("线程%s工作完成...\n", thr_name);

     /* 等待屏障 */
     result = pthread_barrier_wait(&barrier);
     if (result == PTHREAD_BARRIER_SERIAL_THREAD)
         printf("线程%s,wait后第一个返回\n", thr_name);
     )
         printf("线程%s,wait后返回为0\n", thr_name);

     return NULL;
 }

 int main(void)
 {
     pthread_t tid_1, tid_2, tid_3;

     /* 初始化屏障 */
     pthread_barrier_init(&barrier, NULL, PTHREAD_BARRIER_SIZE);

     )
         err_exit("create thread 1");

     )
         err_exit("create thread 2");

     )
         err_exit("create thread 3");

     /* 主线程等待工作完成 */
     pthread_barrier_wait(&barrier);
     printf("所有线程工作已完成...\n");

     sleep();
     ;
 }

28行是线程自己要做的工作,62行的sleep(1)让所有线程有足够的时间把自己的返回值打印出来。编译运行:

可以看到,3个线程工作完成后才可以越过屏障打印返回值,第一个返回的是PTHREAD_BARRIER_SERIAL_THREAD,其他都是0。

这里有一点要注意:我们从运行结果看出,主线程打印"所有线程工作已完成"之后,线程1,线程2还在运行打印返回值。这个结果难免会误解"主线程等待所有线程完成工作之后再向下执行"。区分一点即可:等待只针对屏障之前的动作,越过屏障后,无论是主线程,还是子线程都会并发执行,如果非要让子线程完完全全执行完,可以再加个屏障到线程函数末尾,相应主线程也要加!

linux线程同步(5)-屏障的更多相关文章

  1. 【转】 Linux 线程同步的三种方法

    线程的最大特点是资源的共享性,但资源共享中的同步问题是多线程编程的难点.linux下提供了多种方式来处理线程同步,最常用的是互斥锁.条件变量和信号量. 一.互斥锁(mutex) 通过锁机制实现线程间的 ...

  2. Linux线程同步之读写锁(rwlock)

    读写锁和互斥量(互斥锁)很类似,是另一种线程同步机制,但不属于POSIX标准,可以用来同步同一进程中的各个线程.当然如果一个读写锁存放在多个进程共享的某个内存区中,那么还可以用来进行进程间的同步, 和 ...

  3. linux线程同步(1)-互斥量

    一.概述                                                   互斥量是线程同步的一种机制,用来保护多线程的共享资源.同一时刻,只允许一个线程对临界区进行 ...

  4. Linux线程同步

    1. 线程同步: 当多个控制线程共享相同的内存时,需要确保每个线程看到一致的数据视图.当某个线程可以修改变量,而其他线程也可以读取或者修改这个变量的时候,就需要对这些线程进行同步,以确保他们在访问变量 ...

  5. Linux 线程同步的三种方法(互斥锁、条件变量、信号量)

    互斥锁 #include <cstdio> #include <cstdlib> #include <unistd.h> #include <pthread. ...

  6. Linux线程同步:条件变量

    条件变量通过允许线程阻塞和等待另一个线程发送信号的方法弥补了互斥锁的不足,它常和互斥锁一起使用.使用时,条件变量被用来阻塞一个线程,当条件不满足时,线程往往解开相应的互斥锁并等待条件发生变化.一旦其它 ...

  7. Linux线程同步——条件变量

    互斥锁是用来给资源上锁的,而条件变量是用来等待而不是用来上锁的. 条件变量用来自动阻塞一个线程,直到某特殊情况发生为止. 通常条件变量和互斥锁同时使用. 和条件变量使用有关的几个重要函数: int p ...

  8. linux线程同步实例

    [Linux多线程]三个经典同步问题 - 神奕的专栏 - 博客频道 - CSDN.NET http://blog.csdn.net/lisonglisonglisong/article/details ...

  9. linux 线程同步(二)

    信号量 信号量是相互排斥锁的升级版把相互排斥锁中1变成了n.举个简单的样例:如果如今有10个人,有一部手机.这10个人都竞争来使用手机打电话这就是相互排斥锁.对于信号量,如今可能是有4部手机,这10个 ...

随机推荐

  1. Java的对象初始化过程

    成员变量(字段)初始化顺序 在一个类里初始化的顺序是由成员变量在类里面的定义的顺序来决定的.即使成员变量大量散布于类的各个方法定义的中间,那些成员变量仍会在调用任何方法之前得以初始化,甚至在构造函数调 ...

  2. 玩转Docker之Docker简介(一)

    近几年掀起的docker热潮,可谓席卷全球.什么原因使它这么备受推崇呢?主要是因为它解决了行业痛点.玩linux的都知道,安装个应用时还要先安装所需环境.相关库.解决依赖关系.而docker的出现,很 ...

  3. Summernote – 基于 Bootstrap 的文本编辑器

    Summernote 是一个简单,灵活,所见即所得(WYSIWYG)的编辑器,基于 jQuery 和 Bootstrap 构建.Summernote 所有主要的操作都支持快捷键,有一个功能强大的 AP ...

  4. MySQL之浅谈MySQL的存储引擎

    什么是MySql数据库 通常意义上,数据库也就是数据的集合,具体到计算机上数据库可以是存储器上一些文件的集合或者一些内存数据的集合.     我们通常说的MySql数据库,sql server数据库等 ...

  5. .Net资源总结

    源码文档见官方群(以下为7.4更新内容) 逆天工具 CDN 资源库 国内 Bootstrap中文网开源项目免费 CDN 服务 360网站卫士常用前端公共库CDN服务 百度静态资源公共库 新浪云计算CD ...

  6. 正则中关于修饰符g以及exec和match区别的一个小demo

    代码: 输出结果 补充: reg.lastIndex:下一次正则捕获的开始查找的索引位置 ->正则的懒惰性就是因为默认情况下lastIndex值都是0,我们不管执行几次exec,都是从字符串的开 ...

  7. 使用Python对文档单词进行计数

    做hacker.org上面的题目时,遇到了一个题目需要对RFC3280种长度为9的单词进行计数,并找出这些单词中出现次数最多的那个:Didactic Byte RFC3280文档有7000多行,靠人工 ...

  8. Autodesk 产品开发培训开始报名-8月26~28-武汉– Revit, Vault, Autodesk Viewer, Navisworks

    为了帮助Autodesk中国地区的二次开发人员有机会系统地了解与学习Autodesk 在BIM解决方案中的旗舰产品 Revit以及Navisworks等产品的最新开发技术,并有机会与Autodesk ...

  9. Android.mk相关知识

    Android.mk是Android提供的一种makefile文件,用来指定诸如编译生成so库名.引用的头文件目录.需要编译的.c/.cpp文件和.a静态库文件等.要掌握jni,就必须熟练掌握Andr ...

  10. 优化MySchool数据库(一)

    <优化MyShcool数据库>:能够的独立的分析|设计|创建|运营|你的独立的数据库系统 设计--->实现--->TSQL--->查询优化---->性能优化技术-- ...