线程同步(屏障)

线程同步(屏障)

屏障(barrier)是用户协调多个线程并行工作的同步机制。屏障允许每个线程等待,直到所有的合作线程都达到某一点,然后从该点继续执行。pthread_join函数就是一种屏障,允许一个线程等待,直到另一个线程退出。

但是屏障对象的概念更广,它们允许任意数量的线程等待,直到所有的线程完成处理工作,而线程不需要退出。所有线程达到屏障后可以接着工作。

可以使用pthread_barrier_init函数对屏障进行初始化,用thread_barrier_destroy函数反初始化。


#include <pthread. h>
int pthread_barrier_init(pthread_barrier_t *restrict barrier, const pthread_barrierattr_t *restrict attr, unsigned int count);
int pthread_barrier_destroy(pthread_barrier_t *barrier);
//两个函数的返回值:若成功,返回0;否则,返回错误编码

初始化屏障时,可以使用count参数指定,在允许所有线程继续运行之前,必须到达屏障的线程数目。
可以设置attr为NULL,用默认属性初始化屏障。
如果使用pthread_barrier_init函数为屏障分配资源,那么在反初始化屏障时可以调用pthread_barrier_destroy函数释放相应的资源。

可以使用pthread_barrier_wait函数来表明,线程已完成工作,准备等所有其他线程赶上来。


#include <pthread. h>
int pthread_barrier_wait(pthread_barrier_t *barrier);
//返回值:若成功,返回0或者PTHREAD_BARRIER_SERIAL_THREAD;否则,返回错误编码

调用pthread_barrier_wait的线程在屏障计数(调用pthread_barrier_init时设定)未满足条件时,会进入休眠状态。如果该线程是最后一个调用pthread_barrier_wait的线程,就满足了屏障计数,所有的线程都被唤醒。

对于一个任意线程,pthread_barrier_wait函数返回了PTHREAD_BARRIER_SERIAL_THREAD。剩下的线程看到的返回值是0。这使得一个线程可以作为主线程,它可以工作在其他所有线程已完成的工作结果上。一旦达到屏障计数值,而且线程处于非阻塞状态,屏障就可以被重用。
除非调用了pthread_barrier_destroy函数之后,又调用了pthread_barrier_init函数对计数进行初始化,否则屏障计数不会改变。


实例:

在一个任务上合作的多个线程之间如何用屏障进行同步。


/*
程序功能:
创建一个动态数组,给数组赋初值,创建NUM_THREAD个线程,为长度为SIZE的数组初始化,通过(线程屏障同步)
当所有线程处理完后则打印整个数组的值。通过时间计数来比较所花费的时间。
当采用8个线程时花费sort took 0.0958 seconds
当采用四个线程时
    thread -1249961072 done job.
    thread -1260450928 done job.
    thread -1239471216 done job.
    thread -1270944880 done job.
    sort took 0.1104 seconds
当采用一个线程时
    thread -1239983216 done job.
    sort took 0.2567 seconds
*/
#include <pthread.h>
#include <stdlib.h>
#include <stdio.h>
#define SIZE 8000000L //数组长度
#define NUM_THREAD 8 //线程个数
#define SIZE_PER (SIZE/NUM_THREAD)//每个线程要处理的数组长度
pthread_barrier_t barrier;//定义屏障
int *a;
/*每个线程的线程处理函数*/
void * thr_fun(void *arg)
{
    long n = (long)arg;
    long i;
    for(i=n;i<n+SIZE_PER;i++) {
        a[i] = i;
    }
    printf("thread %d done job.\n",pthread_self());
    pthread_barrier_wait(&barrier); //阻塞等待直到主线程满足了屏障计数
    return ((void *)1);
}
int main()
{
    pthread_t tid;
    struct timeval start,end;
    long long startusec,endusec;
    double elapsed;
    int i;
    a = (int *)malloc(SIZE*sizeof(int)); //动态分配数组
    pthread_barrier_init(&barrier,NULL,NUM_THREAD+1);//初始化线程屏障计数为子线程个数加上主线程
    gettimeofday(&start,NULL);//获得起始时间
    for(i=0;i<NUM_THREAD;i++)
    {
        pthread_create(&tid,NULL,thr_fun,(void *)(i*SIZE_PER));//创建子线程
    }
    pthread_barrier_wait(&barrier);//等待所有子线程处理完成
    gettimeofday(&end,NULL);//获得结束时间
    for(i=0;i<SIZE;i++)//打印数组内容
    //printf("%d ",a[i]);
    startusec = start.tv_sec * 1000000 + start.tv_usec;
    endusec = end.tv_sec * 1000000 + end.tv_usec;
    elapsed = (double)(endusec-startusec)/1000000.0;//计算处理所花费的时间
    printf("sort took %.4f seconds\n",elapsed);
    return 0;
}

  • 0
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值