屏障
屏障是多线程同步的一种方法。barrier意为屏障或者栏杆,把先后到达的多个线程挡在同一栏杆前,直到所有线程到齐,然后撤下栏杆同时放行。先到达的线程将会阻塞,等到所有调用pthread_barrier_wait()函数的线程(数量等于屏障初始化时指定的count)都到达后,这些线程才会由阻塞状态进入就绪状态再次参与系统调度。
屏障是基于条件变量和互斥锁实现的。主要操作包括:调用pthread_barrier_init()初始化一个屏障,其他线程调用pthread_barrier_wait(),所有线程到期后线程唤醒进入准备状态,屏障不在使用调用pthread_barrier_destroy()销毁一个屏障。
屏障控制块
创建一个屏障前需要先定义一个pthread_barrier_t屏障控制块。pthread_barrier_t是pthread_barrier结构体类型的重定义,定义在pthread.h头文件里。
- struct pthread_barrier
- {
- int count; /*指定的等待线程个数*/
- pthread_cond_t cond; /* 条件变量 */
- pthread_mutex_t mutex; /* 互斥锁 */
- };
- typedef struct pthread_barrier pthread_barrier_t;
创建屏障
函数原型
- int pthread_barrier_init(pthread_barrier_t *barrier,
- const pthread_barrierattr_t *attr,
- unsigned count);
- 参数 描述
- attr 指向屏障属性的指针,传入NULL,则使用默认值,非NULL必须使用PTHREAD_PROCESS_PRIVATE
- barrier 屏障句柄
- count 指定的等待线程个数
函数返回
初始化成功返回0,参数无效返回EINVAL。
此函数会创建一个barrier屏障,并根据默认的参数对屏障控制块的条件变量和互斥锁初始化,初始化后指定的等待线程个数为count个,必须对应count个线程 调用pthread_barrier_wait()。
attr一般设置NULL使用默认值即可,具体会在线程高级编程一章介绍。
销毁屏障
函数原型
- int pthread_barrier_destroy(pthread_barrier_t *barrier);
- 参数 描述
- barrier 屏障句柄
函数返回
销毁成功返回0,参数无效返回EINVAL。
此函数会销毁一个barrier屏障。销毁之后屏障的属性及控制块参数将不在有效,但可以调用pthread_barrier_init()重新初始化。
等待屏障
函数原型
- int pthread_barrier_wait(pthread_barrier_t *barrier);
- 参数 描述
- barrier 屏障句柄
函数返回
等待成功返回0,参数无效返回EINVAL,死锁返回EDEADLK。
此函数同步等待在barrier前的线程,由每个线程主动调用,若屏障等待线程个数count不为0,count将减1,若减1后count为0,表明所有线程都已经到达栏杆前,所有到达的线程将被唤醒重新进入就绪状态,参与系统调度。若减一后count不为0,表明还有线程没有到达屏障,调用的线程将阻塞直到所有线程到达屏障。
屏障示例代码
此程序会创建3个线程,初始化一个屏障,屏障等待线程数初始化为3。3个线程都会调用pthread_barrier_wait()等待在屏障前,当3个线程都到齐后,3个线程进入就绪态,之后会每隔2秒打印输出计数信息。
- #include <pthread.h>
- #include <unistd.h>
- #include <stdio.h>
- /* 线程控制块 */
- static pthread_t tid1;
- static pthread_t tid2;
- static pthread_t tid3;
- /* 屏障控制块 */
- static pthread_barrier_t barrier;
- /* 函数返回值检查函数 */
- static void check_result(char* str,int result)
- {
- if (0 == result)
- {
- printf("%s successfully!\n",str);
- }
- else
- {
- printf("%s failed! error code is %d\n",str,result);
- }
- }
- /*线程1入口函数*/
- static void* thread1_entry(void* parameter)
- {
- int count = 0;
- printf("thread1 have arrived the barrier!\n");
- pthread_barrier_wait(&barrier); /* 到达屏障,并等待其他线程到达 */
- while (1)
- {
- /* 打印线程计数值输出 */
- printf("thread1 count: %d\n",count ++);
- /* 休眠2秒*/
- sleep(2);
- }
- }
- /*线程2入口函数*/
- static void* thread2_entry(void* parameter)
- {
- int count = 0;
- printf("thread2 have arrived the barrier!\n");
- pthread_barrier_wait(&barrier);
- while (1)
- {
- /* 打印线程计数值输出 */
- printf("thread2 count: %d\n",count ++);
- /* 休眠2秒*/
- sleep(2);
- }
- }
- /* 线程3入口函数 */
- static void* thread3_entry(void* parameter)
- {
- int count = 0;
- printf("thread3 have arrived the barrier!\n");
- pthread_barrier_wait(&barrier);
- while (1)
- {
- /* 打印线程计数值输出 */
- printf("thread3 count: %d\n",count ++);
- /* 休眠2秒*/
- sleep(2);
- }
- }
- /* 用户应用入口 */
- int rt_application_init()
- {
- int result;
- pthread_barrier_init(&barrier,NULL,3);
- /*创建线程1,线程入口是thread1_entry, 属性参数设为NULL选择默认值,入口参数为NULL*/
- result = pthread_create(&tid1,NULL,thread1_entry,NULL);
- check_result("thread1 created",result);
- /*创建线程2,线程入口是thread2_entry, 属性参数设为NULL选择默认值,入口参数为NULL*/
- result = pthread_create(&tid2,NULL,thread2_entry,NULL);
- check_result("thread2 created",result);
- /*创建线程3,线程入口是thread3_entry, 属性参数设为NULL选择默认值,入口参数为NULL*/
- result = pthread_create(&tid3,NULL,thread3_entry,NULL);
- check_result("thread3 created",result);
- }