go sync.Cond 源码解析
一、什么是Cond?
Cond实现了一个条件变量,它是一个/多个goroutine等待或宣布事件发生的集合点。
每个Cond都有一个相关联的锁定器L(通常是*Mutex或*RWMutex),当改变条件和调用Wait方法时必须持有该锁。
Cond在第一次使用后不得复制。
二、Cond 结构体
type Cond struct {noCopy noCopy// L is held while observing or changing the conditionL Lockernotify notifyListchecker copyChecker
}
noCopy:防止Cond复制
L Locker:锁接口,必须实现Lock、Unlock方法
notify:通告链表
checker:copyChecker保留指向自身的指针来检测对象复制。
三、方法
1. NewCond - 实例化Cond
func NewCond(l Locker) *Cond {return &Cond{L: l}
}
2. Wait - 阻塞当前gorotine,并等待Signal/Broadcast方法唤醒,前提是先获得锁(Lock()),然后执行Wait,再释放锁(Unlock)
func (c *Cond) Wait() {c.checker.check() //检测Cond是否被复制,如果被复制,则panic//将当前goroutine添加到等待队列(Cond.notify)t := runtime_notifyListAdd(&c.notify)c.L.Unlock()// 解锁;调用Wait前,需要加锁//进入睡眠,等待被唤醒runtime_notifyListWait(&c.notify, t)c.L.Lock() // 加锁,调用Wait之后,需要解锁
}
3. Signal - 唤醒一个goroutine(Cond.notify)
func (c *Cond) Signal() {c.checker.check() // 检测Cond是否被复制,如果被复制,则panic//唤醒一个notify链表里的goroutineruntime_notifyListNotifyOne(&c.notify)
}
4.Broadcast - 唤醒所有睡眠中的goroutine(Cond.notify)
func (c *Cond) Broadcast() {c.checker.check() //检测Cond是否被复制,如果被复制,则panic//唤醒所有goroutineruntime_notifyListNotifyAll(&c.notify)
}
四、noCopy
noCopy可以嵌入到第一次使用后不能复制的结构体中。
type noCopy struct{}// Lock is a no-op used by -copylocks checker from `go vet`.
func (*noCopy) Lock() {}
func (*noCopy) Unlock() {}
五、copyChecker
copyChecker保留指向自身的指针来检测对象复制。
type copyChecker uintptrfunc (c *copyChecker) check() {if uintptr(*c) != uintptr(unsafe.Pointer(c)) &&!atomic.CompareAndSwapUintptr((*uintptr)(c), 0, uintptr(unsafe.Pointer(c))) &&uintptr(*c) != uintptr(unsafe.Pointer(c)) {panic("sync.Cond is copied")}
}
六、小结
Cond使用NewCond注入锁,获取Cond指针;
调用Lock加锁,调用Wait使当前goroutine进入睡眠,唤醒后,使用Unlock解锁。
唤醒方式:Signal,Broadcast
进一步阅读:
Cond中的notify,在runtime/sema.go,notifyList对应的方法也在其中,runtime_notifyListAdd、runtime_notifyListWait、runtime_notifyListNotifyOne、runtime_notifyListNotifyAll
sema.go中的代码都有相关注释,稍加思索,便可以明白其中的原理。
go sync.Cond 源码解析相关推荐
- go学习笔记 sync/Cond源码
Cond需要指定一个Locker,通常是一个*Mutex或*RWMutex. func (c *Cond) Broadcast() 和 func (c *Cond) Signal() 唤醒因wait ...
- Colly源码解析——结合例子分析底层实现
通过<Colly源码解析--框架>分析,我们可以知道Colly执行的主要流程.本文将结合http://go-colly.org上的例子分析一些高级设置的底层实现.(转载请指明出于break ...
- 死磕 java同步系列之ReentrantReadWriteLock源码解析
问题 (1)读写锁是什么? (2)读写锁具有哪些特性? (3)ReentrantReadWriteLock是怎么实现读写锁的? (4)如何使用ReentrantReadWriteLock实现高效安全的 ...
- kube-proxy源码解析
kube-proxy源码解析 ipvs相对于iptables模式具备较高的性能与稳定性, 本文讲以此模式的源 码解析为主,如果想去了解iptables模式的原理,可以去参考其实现,架构上无差别. ku ...
- Go http源码解析(一)
Go web之旅 此篇开始将开启Go web之旅,我将这趟旅途分为三个子旅程: 源码解析 框架解读 中间件使用 所以在这趟旅途中我们将领略源码之雄伟,框架之奇艳,中间件之灵秀.在接下来的时间里我会按照 ...
- 多线程(三)之ReentrantLock源码解析
2019独角兽企业重金招聘Python工程师标准>>> 今天分析ReentrantLock类的源码,在看源码之前,先学习AQS(AbstractQueuedSynchronizer) ...
- dubbo源码解析(九)远程通信——Transport层
远程通讯--Transport层 目标:介绍Transport层的相关设计和逻辑.介绍dubbo-remoting-api中的transport包内的源码解析. 前言 先预警一下,该文篇幅会很长,做好 ...
- Android Lifecycle源码解析(一)
Android Lifecycle源码解析(一) 首先我们看HomeActivity中我们添加到一行代码 public class HomeActivity extends AppCompatActi ...
- latch.await java有什么作用_java相关:CountDownLatch源码解析之await()
java相关:CountDownLatch源码解析之await() 发布于 2020-6-18| 复制链接 摘记: CountDownLatch 源码解析-- await(),具体内容如下上一篇文章说 ...
最新文章
- android课程设计录音机,[转载]数字录音机(微机原理与接口技术-课程设计)
- 万维网发布服务 w3svc 已停止 除非万维_W3C万维网联盟宣布停止发布HTML 5.3版
- 处理xmpp 离线信息,
- C学习if条件判断和for循环
- Linux之ansible 自动化运维工具
- java微信h5支付_java 微信H5支付
- 【阅读推荐】改变你思维模式的书单
- Python一个命令开启http下载服务器
- 这条命令帮我在一分钟内修改了200台远程服务器密码!
- web前端学习第三周
- java listview用法_2.4.5 ListView简单实用
- 2007版本中国网络新秀之七剑下天山
- 常见的27个电源符号
- 视频摘要和视频浓缩的区别
- 短视频运营详解:抖音变现目前流行的是七种方式之一电商卖货
- 小x与三角形 c语言 1秒,[2019年第一水] 小x与神牛
- Python入门习题大全——猫和狗
- Axure RP 8.1 下载(附汉化+注册码)
- AcWing 1089 烽火传递 题解(动态规划—DP—单调队列优化DP)
- 合肥火车站为乌鲁木齐疼痛男孩开辟绿色通道
热门文章
- SAP License:SAP系统备料发货时的流程规范
- 20个基于DPDK开源项目,建议收藏
- 3.28leet28
- 【工欲善其事必先利其器】论文编辑及文献管理(Endnote,Latex,JabRef ,overleaf)资源下载及使用指南
- 我的世界服务器文件翻译,我的世界server.properties翻译 联机参数设置攻略
- fatal error C1001: INTERNAL COMPILER ERROR(compiler file 'msc1.cpp', line 1786)解决方法
- WinForm 窗体的边框
- 2021年的保研之旅总结
- Python股票数据爬虫解读
- 正片叠底(Multiply)和滤色(Screen)是两种基本的混合模式