博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
libuv中的Barrier
阅读量:5325 次
发布时间:2019-06-14

本文共 2458 字,大约阅读时间需要 8 分钟。

Wiki:

In parallel computing, a barrier is a type of synchronization method. A barrier for a group of threads or processes in the source code means any thread/process must stop at this point and cannot proceed until all other threads/processes reach this barrier.

简言之就是要等到指定数目的线程一起到达才能一起继续执行。

libuv中对于barrier结构的定义:

typedef struct {  unsigned int n;              //对于当前等待线程的计数  unsigned int count;        //设置的总数  uv_mutex_t mutex;        //结构体内操作同步用  uv_sem_t turnstile1;        //turnstile意为旋转门,这里1和2分别表示一起进和一起出  uv_sem_t turnstile2;} uv_barrier_t;

初始化

int uv_barrier_init(uv_barrier_t* barrier, unsigned int count) {  int err;  barrier->n = count;  barrier->count = 0;  err = uv_mutex_init(&barrier->mutex);  if (err)    return err;  err = uv_sem_init(&barrier->turnstile1, 0);  if (err)    goto error2;  err = uv_sem_init(&barrier->turnstile2, 1);  if (err)    goto error;  return 0;error:  uv_sem_destroy(&barrier->turnstile1);error2:  uv_mutex_destroy(&barrier->mutex);  return err;}

销毁

void uv_barrier_destroy(uv_barrier_t* barrier) {  uv_sem_destroy(&barrier->turnstile2);  uv_sem_destroy(&barrier->turnstile1);  uv_mutex_destroy(&barrier->mutex);}

接下来是最重要的代码:

1 int uv_barrier_wait(uv_barrier_t* barrier) { 2   int serial_thread; 3  4   uv_mutex_lock(&barrier->mutex); 5   if (++barrier->count == barrier->n) { 6     uv_sem_wait(&barrier->turnstile2); 7     uv_sem_post(&barrier->turnstile1); 8   } 9   uv_mutex_unlock(&barrier->mutex);10 11   uv_sem_wait(&barrier->turnstile1);12   uv_sem_post(&barrier->turnstile1);13 14   uv_mutex_lock(&barrier->mutex);15   serial_thread = (--barrier->count == 0);16   if (serial_thread) {17     uv_sem_wait(&barrier->turnstile1);18     uv_sem_post(&barrier->turnstile2);19   }20   uv_mutex_unlock(&barrier->mutex);21 22   uv_sem_wait(&barrier->turnstile2);23   uv_sem_post(&barrier->turnstile2);24   return serial_thread;25 }

当没有达到设置的阈值的时候,代码直接通过4-9行,在11行阻塞。直到指定数目的线程到达,进入4-9行,将第一扇门打开(turnstile1变为1),第二扇门关上(turnstile2变为0)。

然后刚才等待在第一扇门的第一个线程就可以通过11行,当这个线程通过后(此时turnstile变为0),再将turnstile置为1,让后一个线程可以通过。当前线程通过14-20行(此时barrier->count已变为最大值),会等待在22行。

当最后一个线程都通过了14行后,会进入16行的判断块内,此时它将第一扇门关上,第二扇门打开(turnsatile1变为0,turnsatile2变为1)。此时所有等在22行线程都可以继续执行,还是同过第一扇门的时候相同,它们是一个个接力过第二扇门的。

至此,所有线程全部通过了这两扇门。

思考:为什么需要14行后的代码,当凑齐数目后一起通过不是就完成任务了么?为什么还要一起出这个函数呢?

如果不加后面逻辑,考虑下面的情况。当N个线程全部到达第一扇门后,有两个线程出了这个函数。这个时候又有第N+1线程到达这个函数了,那么最终这第N+1个线程,也会一起出这个函数,那么总共有N+1个线程通过了这个函数。
View Code

 

转载于:https://www.cnblogs.com/rushyourmind/p/5601031.html

你可能感兴趣的文章
Hyper-V虚拟机上安装一个图形界面的Linux系统
查看>>
js千分位处理
查看>>
Mac---------三指拖移
查看>>
字符串类型的相互转换
查看>>
HTTP状态码
查看>>
iOS如何过滤掉文本中特殊字符
查看>>
基础学习:C#中float的取值范围和精度
查看>>
javaagent 简介
查看>>
python升级安装后的yum的修复
查看>>
Vim配置Node.js开发工具
查看>>
web前端面试题2017
查看>>
ELMAH——可插拔错误日志工具
查看>>
MySQL学习笔记(四)
查看>>
【Crash Course Psychology】2. Research & Experimentation笔记
查看>>
两数和
查看>>
移动设备和SharePoint 2013 - 第3部分:推送通知
查看>>
SOPC Builder中SystemID
查看>>
MySQL数据库备份工具mysqldump的使用(转)
查看>>
NTP服务器配置
查看>>
关于 linux 的 limit 的设置
查看>>