使用场景
这种“栏杆”机制最大的特点就是最后一个执行wait的动作最为重要,
pthread_barrier_xxx让所有线程等待,所有线程准备好后再一起行动。
如pthread_create()生成100个线程,每个子线程在被create出的瞬间就会自顾自的立刻进入回调函数运行。
但我们可能不希望它们这样做,因为这时主进程还没准备好,和它们一起配合的其它线程还没准备好,我们希望它们在回调函数中申请完线程空间、初始化后停下来,
一起等待主进程释放一个“开始”信号,然后所有线程再开始执行业务逻辑代码。
/*
函数名:uv_barrier_init
参 数:uv_barrier_t* barrier -- barrier指针
参 数:unsigned int count -- 线程数量
说 明:初始化barrier指针,等待同步count个线程。
*/
int uv_barrier_init(uv_barrier_t* barrier, unsigned int count);
/*
函数名:uv_barrier_wait
参 数:uv_barrier_t* barrier -- barrier指针
说 明:等待n个线程全部执行完成,才往下执行
*/
int uv_barrier_wait(uv_barrier_t* barrier);
/*
函数名:uv_barrier_destroy
参 数:uv_barrier_t* barrier -- barrier指针
说 明:释放barrier资源
*/
void uv_barrier_destroy(uv_barrier_t* barrier);
#include <cstdio>
#include <stdio.h>
#include <stdlib.h>
#include <libuv/uv.h>
//同步栏杆
uv_barrier_t blocker;
//读写锁
uv_rwlock_t numlock;
//共享变量
int shared_num;
void reader(void* n)
{
int num = *(int*)n;
int i;
for (i = 0; i < 5; i++) {
//读锁
uv_rwlock_rdlock(&numlock);
printf("Reader %d: acquired lock
", num);
printf("Reader %d: shared num = %d
", num, shared_num);
uv_rwlock_rdunlock(&numlock);
printf("Reader %d: released lock
", num);
}
//线程需要等待其他一些线程任务完成之后,才能继续运行时
uv_barrier_wait(&blocker);
}
void writer(void* n)
{
int num = *(int*)n;
int i;
for (i = 0; i < 5; i++) {
//写锁
uv_rwlock_wrlock(&numlock);
printf("Writer %d: acquired lock
", num);
shared_num++;
printf("Writer %d: incremented shared num = %d
", num, shared_num);
uv_rwlock_wrunlock(&numlock);
printf("Writer %d: released lock
", num);
}
//线程需要等待其他一些线程任务完成之后,才能继续运行时
uv_barrier_wait(&blocker);
}
int main()
{
//初始化要同步的线程个数n + 1
uv_barrier_init(&blocker, 4);
shared_num = 0;
uv_rwlock_init(&numlock);
uv_thread_t threads[3];
int thread_nums[] = { 1, 2, 3 };
uv_thread_create(&threads[0], reader, &thread_nums[0]);
uv_thread_create(&threads[1], reader, &thread_nums[1]);
uv_thread_create(&threads[2], writer, &thread_nums[2]);
//线程需要等待其他一些线程任务完成之后,才能继续运行时
uv_barrier_wait(&blocker);
uv_barrier_destroy(&blocker);
uv_rwlock_destroy(&numlock);
return 0;
}