多routine场景sync.Cond的locker锁混乱问题

Atticus · · 200 次点击 · 开始浏览    置顶
## 标签 ```routine```、```sync.Mutex```、 ```sync.Cond``` ## 场景 利用```sync.Cond```的Broadcast()方法唤醒3个routine ## 过程 **代码** ```golang package main import ( "fmt" "sync" "time" ) func main() { wg := sync.WaitGroup{} mux := sync.Mutex{} cond := sync.NewCond(&mux) wg.Add(3) for i := 0; i < 2; i++ { go func(num int) { defer wg.Done() fmt.Println("routine", num, "开始处理") mux.Lock() fmt.Println(" routine", num, "锁住了mux @", time.Now()) cond.Wait() fmt.Println(" routine", num, "马上解锁mux @", time.Now()) mux.Unlock() }(i) } go func() { defer wg.Done() time.Sleep(time.Second * 10) fmt.Println("预备,开始!") cond.Broadcast() }() wg.Wait() } ``` > 逻辑解释 > > 1、启动2个routine,在每个routine中: > * 1) 申请锁住mux > > * 2) 等待cond的广播信号 > > * 3) 解锁mux > > 2、再启动一个routine,等待10秒后触发cond.Broadcast(),唤醒1.2)之后的操作 **执行结果** ```text routine 0 开始处理 routine 1 开始处理 routine 0 锁住了mux @ 2020-10-28 18:49:23.1134126 +0800 CST m=+0.003989001 routine 1 锁住了mux @ 2020-10-28 18:49:23.1333588 +0800 CST m=+0.023935201 预备,开始! routine 1 马上解锁mux @ 2020-10-28 18:49:33.1143597 +0800 CST m=+10.004936101 routine 0 马上解锁mux @ 2020-10-28 18:49:33.1143597 +0800 CST m=+10.004936101 Process finished with exit code 0 ``` ## 结果分析 从结果看,两个等待的routine在彼此释放锁mux之前都分别获取到了mux的锁,这是比较怪异的地方,让我们来看一下sync.Cond.Wait()方法的逻辑: ```golang func (c *Cond) Wait() { c.checker.check() t := runtime_notifyListAdd(&c.notify) c.L.Unlock() // 原来幺蛾子出在这儿,在routine执行mux.Unlock()方法之前,sync.Cond先执行了,这就导致另一个routine逮到了机会,锁住了mux runtime_notifyListWait(&c.notify, t) c.L.Lock() } ``` 那么问题来了,针对这个场景,应该怎样使用sync.Cond与sync.Mutex配合routine实现最初的目的呢,求大佬科普 ???

有疑问加站长微信联系(非本文作者)

入群交流(和以上内容无关):加入Go大咖交流群,或添加微信:liuxiaoyan-s 备注:入群;或加QQ群:1006366459

200 次点击  
加入收藏 微博
1 回复  |  直到 2020-10-29 11:23:08
暂无回复
添加一条新回复 (您需要 登录 后才能回复 没有账号 ?)
  • 请尽量让自己的回复能够对别人有帮助
  • 支持 Markdown 格式, **粗体**、~~删除线~~、`单行代码`
  • 支持 @ 本站用户;支持表情(输入 : 提示),见 Emoji cheat sheet
  • 图片支持拖拽、截图粘贴等方式上传