线程总结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章