UNIX多线程环境下屏障功能(barrier)浅析
说起屏障这个东西,相信对于大多数朋友来说比较陌生,不过要是说起pthread_join这个函数,相信都比较熟悉。我们通常使用这个函数来等待其它线程结束,例如主线程创建一些线程,这些线程去完成一些工作,而主线程需要去等待这些线程结束。其实pthread_join就实现了一种屏障。我们可以对屏障这样理解,把屏障理解为为了协同线程之间的工作而使得某一具体线程进入等待状态的一种机制。下面我们来看看UNIX为我们提供的一个屏障——barrier。
注:与所有的线程函数一样,使用屏障barrier时需要包含头文件pthread.h,编译时需要添加参数 -lpthread
屏障barrier的相关结构:pthread_barrier_t
初始化屏障结构函数:int pthread_barrier_init(pthread_barrier_t *restrict barrier, const pthread_barrierattr_t *restrict attr, unsigned int count);
函数执行成功返回 0,执行失败则返回一个错误号,我们可以通过该错误号获取相关的错误信息
函数第一个参数:一个指向pthread_barrier_t 类型的指针,我们必须要指出的是pthread_barrier_init函数不会给指针分配相关内存空间,因此我们传入的指针必须为一个pthread_barrier_t 变量
函数第二个参数:用于指定屏障的细节参数,我们这里可以暂且不去管它,如果我们传入NULL,那么系统将按照默认情况处理
函数第三个参数:设计屏障等待的最大线程数目
销毁屏障函数:int pthread_barrier_destory(pthread_barrier_t *barrier);
函数执行成功返回 0,执行失败则返回一个错误号,我们可以通过该错误号获取相关的错误信息
函数参数:指向pthread_barrier_t 变量的指针
我们需要注意的是,当一个屏障被使用完(即屏障已经等待了足够数目的线程后)就应该被销毁,故一个屏障我们不能复用,除非我们将它销毁并重新初始化
屏障等待函数:int pthread_barrier_destory(pthread_barrier_t *barrier);
函数执行成功返回 0,执行失败则返回一个错误号,我们可以通过该错误号获取相关的错误信息
函数参数:指向pthread_barrier_t 变量的指针
一个线程需要等待其它多个线程结束时,调用该函数
在这里我们需要注意的是使用barrier这个屏障我们无法获取线程的结束状态,若想要获取相关线程结束状态我们仍然需要调用pthread_join函数。当然我们一般也不会把pthread_barrier_wait 放在某个线程结束时候,这显然是很无聊的,这个函数调用往往出现在线程之间的某个位置,接下来线程等待其它协同线程到达屏障后再处理一些其它事务。
Barriers 是一种基本的同步原语,它可以告诉你一组线程在什么时候完成了各自的任务可以接下来进行其他的工作,即一旦所有的线程都到达了屏障点,它们才能够继续执行下去,否则先到达屏障点的线程就会在此处等待其他线程的到来,鉴于此,屏障操作也是一个相当重量级的同步操作。