Cond条件变量

针对场景

应用于一组goroutine等待某一个条件,当条件为true时唤醒某一个或者所有的goroutine

源码解读

type Cond struct {noCopy noCopyL Locker  //当观察(Wait方法)或者修改条件时加锁,Wait方法用锁是保护等待队列的并发安全notify  notifyList   //等待队列checker copyChecker    //运行时检查是否存在复制使用
}// NewCond returns a new Cond with Locker l.
func NewCond(l Locker) *Cond {return &Cond{L: l}
}func (c *Cond) Wait() {c.checker.check()     //检查是否存在复制使用t := runtime_notifyListAdd(&c.notify)   //把调用的goroutine扔到等待队列c.L.Unlock()   //解锁,所以调用Wait前要调用Lock,否则会panicruntime_notifyListWait(&c.notify, t)    //阻塞等待(调用gopark)c.L.Lock()    //加锁,所以最后一次等待被唤醒后要调用一次UnLock解锁
}func (c *Cond) Signal() {c.checker.check()runtime_notifyListNotifyOne(&c.notify)   //唤醒队列头部的goroutine
}func (c *Cond) Broadcast() {c.checker.check()runtime_notifyListNotifyAll(&c.notify)   //唤醒队列所有goroutine
}

使用示例

import ("fmt""sync""time"
)func condUseCase() {/*功能:十个运动员、一个裁判,裁判要等待十个运动员都准备就绪后才能开始比赛*/cond := sync.Cond{L: new(sync.Mutex),}ready := 0for i := 0; i < 10; i++ {i := igo func() {time.Sleep(time.Duration(i) * time.Millisecond)cond.L.Lock()ready++cond.L.Unlock()fmt.Printf("运动员%v号准备就绪\n", i)cond.Signal()}()}cond.L.Lock() //Wait方法会调用UnLock,所以要先Lock一下for ready != 10 {cond.Wait()println("裁判被唤醒")}cond.L.Unlock() //条件满足,最后一次Wait唤醒后会调用Lock,所以要UnLock一下println("所有运动员准备就绪")
}

常见踩坑

调用Wait前未加锁

因为Wait内部把当前goroutine扔到等待队列后会调用Unlock解锁,所以调用Wait前要调用Lock加锁,否则会panic

最后一次Wait返回后未解锁

Wait内部被唤醒后会调用Lock方法拿锁准备保护等待队列,但是最后一次Wait被唤醒后发现条件满足就不会操作等待队列后执行Unlock了,所以要在最后一个Wait返回后调用Unlock解锁

调用Wait后,没有检查条件是否满足就继续执行了

Wait方法返回不代表条件已经满足了,需要检查条件是否满足,如果满足继续执行,否则执行Wait继续等待

总结

使用Cond的场景大部分都可以使用Chan代替
Chan代替用法:创建一个没有buffer的chan,等待的goroutine从chan中获取元素阻塞,往chan中传入元素可以唤醒一个goroutine(Signal)、关闭chan可以唤醒所有goroutine(BroadCast)
使用Chan替代上面的示例:

func chanUseCase() {condChan := make(chan struct{})var mu sync.Mutexready := 0for i := 0; i < 10; i++ {i := igo func() {time.Sleep(time.Duration(i) * time.Millisecond)mu.Lock()ready++mu.Unlock()fmt.Printf("运动员%v号准备就绪\n", i)condChan <- struct{}{}}()}for ready != 10 {<-condChanprintln("裁判被唤醒")}println("所有运动员准备就绪")
}

Cond有三个特性Chan无法满足:

  1. Cond本身具有Locker,不需要创建额外的Locker保证条件的并发修改安全
  2. Cond可以调用多次BroadCast,但是Chan只能调用一次close

Cond:条件变量源码解读相关推荐

  1. PostgreSQL 源码解读(32)- 查询语句#17(查询优化-表达式预处理#2)

    本节简单介绍了PG查询优化表达式预处理中常量的简化过程.表达式预处理主要的函数主要有preprocess_expression和preprocess_qual_conditions(调用preproc ...

  2. 源码解读Mybatis List列表In查询实现的注意事项

    http://www.blogjava.net/xmatthew/archive/2011/08/31/355879.html 在SQL开发过程中,动态构建In集合条件查询是比较常见的用法,在Myba ...

  3. Java Review - Queue和Stack 源码解读

    文章目录 Pre 概述 Queue Deque ArrayDeque 一览 构造函数 属性 方法 addFirst() addLast() pollFirst() pollLast() peekFir ...

  4. Spring5源码 - 05 invokeBeanFactoryPostProcessors 源码解读_2

    文章目录 Pre 源码解读 总体流程 源码分析 细节解析 [初始化对应的集合 & 遍历用户自己手动添加的后置处理器] [调用实现了PriorityOrdered接口的BeanDefinitio ...

  5. Ubuntu 16.04下Caffe-SSD的应用(四)——ssd_pascal.py源码解读

    前言 caffe-ssd所有的训练时的参数,全部由ssd_pascal.py来定义,之后再去调用相关的脚本和函数,所以想要训练自己的数据,首先要明白ssd_pascal.py各个定义参数的大体意思. ...

  6. php yii框架源码,yii 源码解读

    date: 2017-11-21 18:15:18 title: yii 源码解读 本篇博客阅读指南: php & 代码提示: 工欲善其事必先利其器 yii 源码阅读指南: 整体上全貌上进行了 ...

  7. aqs java 简书,Java AQS源码解读

    1.先聊点别的 说实话,关于AQS的设计理念.实现.使用,我有打算写过一篇技术文章,但是在写完初稿后,发现掌握的还是模模糊糊的,模棱两可. 痛定思痛,脚踏实地重新再来一遍.这次以 Java 8源码为基 ...

  8. Linux内核网络协议栈:udp数据包发送(源码解读)

    <监视和调整Linux网络协议栈:接收数据> <监控和调整Linux网络协议栈的图解指南:接收数据> <Linux网络 - 数据包的接收过程> <Linux网 ...

  9. python库源码分析_python第三方库Faker源码解读

    源码背景 Faker是一个Python第三方库,GITHUB开源项目,主要用于创建伪数据创建的数据包含地理信息类.基础信息类.个人账户信息类.网络基础信息类.浏览器信息类.文件信息类.数字类 文本加密 ...

最新文章

  1. Spring AOP AspectJ Pointcut Expressions With Examples--转
  2. 广告片断大收集+穿帮镜头
  3. redis 基于主从复制的 rce 利用方式
  4. 机器学习-MNIST数据集-神经网络
  5. 如何用Python进行大数据挖掘和分析
  6. 板式橡胶支座弹性模量怎样计算_Midas Civil支座模拟的详细解决方法
  7. iOS 使用 socket 即时通信(非第三方库)
  8. 2017.3.16 下午
  9. clearcase 常用命令
  10. linux 迅雷 命令行,Linux小迅雷:uGet下载工具加速 | 薄荷开源网
  11. html测试身高体重,【 身高体重测试】_如何测试_注意事项-大众养生网
  12. P1567 统计天数
  13. Springboot无法启动:At least one base package must be specified
  14. codevs 2867 天平系统3
  15. 自己写的12306买火车票手机APP
  16. python获取当前进程pid_Python获取系统所有进程PID及进程名称的方法示例
  17. 计算机写给未来自己的一段话,现实,致自己 写给自己的霸气一段话汇总73句
  18. 李宏毅——一天搞懂深度学习PPT学习笔记
  19. 假作真时真亦假——“真实”IP带来的安全隐患
  20. oracle数据库的scn,Oracle数据库SCN详解

热门文章

  1. 牧牛海派战法,区块链对经济社会的影响
  2. 不会做动画的程序猿不是好的动画师(如何用css3动画做动画)
  3. ONF完成业界首个基于SDN的无线传输PoC
  4. 如何使用阿里云国际版控制台使用海外云服务器-Unirech
  5. 深度学习超分辨率综述阅读笔记(翻译)
  6. c# m4a文件转mp3文件 【.net】
  7. cad断点快捷键_史上最好的CAD常用快捷键及使用方法集
  8. 支付宝「银行卡绑定流程」设计资源分享
  9. sincerit Protoss and Zerg(快速幂求组合)
  10. 获取Jenkins项目名称