线程总结3-屏障

0. 屏障

屏障是用户协调多个线程并行工作的同步机制。屏障允许所有的合作线程都到达某一点,然后从该点继续执行。

1. 相关函数

1.1. 初始化

#include<pthread.h>
int pthread_barrier_init(pthread_barrier_t *restrict barrier,
                        const pthread_barrierattr_t *restrict attr, 
                        unisgned int count);
int pthread_barrier_destory(pthread_barrier_t *barrier);

count 参数设置允许所有线程继续执行之前吗,必须达到屏障的线程数目。

1.2. wait函数

int pthread_barrier_wait(pthread_barrier_t *barrier);

调用pthread_barrier_wait函数的线程在屏障计数没有达到count时,会进入休眠状态。如果该线程是最后一个调用pthread_barrier_wait的线程,就满足了屏障计数,所有线程都会被唤醒。

对于一个任意线程,pthread_barrier_wait函数返回了PTHREAD_BARRIER_SERIAL_THREAD。剩下的线程看到的返回值都是0。这使得一个线程可以作为主线程,它可以工作在其他所有线程已完成的工作结果上。

2. 例程

例程1: 老师给10个学生各自分配一个task,task难易程度不同,因此耗时也不尽相同。每个学生完成自己的task后,输出"task[i] accomplished in m minutes!"。等到所有同学都完成了各自任务,老师宣布"mission accomplished!"

#include<pthread.h>
#define NTHR 10
void* task(void *arg);

pthread_barrier_t barrier;

int main()
{
    int err, i;
    pthread_t tid;

    pthread_barrier_init(&barrier, NULL, NTHR + 1);
    for (i = 0; i < NTHR; i++) {
        err = pthread_create(&tid, NULL, task, (void*)(i));
        if (err != 0) {
            printf("create thread error!\n");
            return -1;
        }
    }
    pthread_barrier_wait(&barrier);
    printf("mission accomplished!\n");
    return 0;
}

void* task(void *arg)
{
    int i, t;

    i = (int)arg;
    t = rand() % 10 + 1;
    // 睡几秒钟,假装我们在执行任务
    sleep(t); 
    printf("task %d accomplished in %d minutes\n", i, t);
    pthread_barrier_wait(&barrier);
    return ((void*)0);
}

完整例程参见barrier-ex01.c

例程2: 对1000万个随机数进行排序。

在这个例子中,我们创建了100个线程,每个线程对10万个数字进行堆排序,排序完成后,在主线程进行合并。

int main()
{
    int err, i;
    pthread_t tid;
    printf("INT_MAX = %d\n", INT_MAX);

    srand(time(NULL));  
    for (i = 0; i < NUMNUM; i++) {
        // sleep_ms(1);
        nums[i] = rand() % INT_MAX;
    }

    // 初始化barrier
    pthread_barrier_init(&barrier, NULL, NTHR + 1);
    // 创建100个排序线程
    for (i = 0; i < NTHR; i++) {
        err = pthread_create(&tid, NULL, sort, (void*)(i * TNUM));
        if (err != 0) {
            printf("create thread error!\n");
            return -1;
        }
    }
    
    pthread_barrier_wait(&barrier);
    //合并排序结果
    merge();
    printf("-------------------------------------\n");
    for (i = 0; i < NUMNUM; i++) {
        // nums[i] = random();
        printf("%10d \n", nums[i]);
        if ((i + 1) % TNUM == 0) {
            printf("-------------------------------------\n");
        }
    }
    return 0;
}

完整例程参见barrier-ex02.c

3.参考资料

[1.] 《unix环境高级编程》第11章