

sync.Cond学习笔记
source link: https://studygolang.com/articles/31846
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

sync.Cond
go/sync
sync.Cond用于goroutine之间的协作,用于协程的挂起和唤醒。当多个协程之间协作时,有可能一个协程需要依赖别的协程完成后再进行某种操作,这时可依据管道进行通信,这对于两个协程之间是比较方便的。但若是多个协程依赖一个协程的完成后再进行某种操作,那么就可以使用sync.Cond来实现了;
例子:
package main import ( "fmt" "sync" "time" ) var locker = new(sync.Mutex) var cond = sync.NewCond(locker) func main() { for i := 0; i < 40; i++ { go func(x int) { cond.L.Lock() //获取锁 cond.Wait() //等待通知,阻塞当前goroutine cond.L.Unlock() //释放锁 fmt.Println(x) time.Sleep(time.Second * 1) }(i) } time.Sleep(time.Second * 1) fmt.Println("Signal...") cond.Signal() // 下发一个通知给已经获取锁的goroutine time.Sleep(time.Second * 1) cond.Signal() // 3秒之后 下发一个通知给已经获取锁的goroutine time.Sleep(time.Second * 3) cond.Broadcast() //3秒之后 下发广播给所有等待的goroutine fmt.Println("Broadcast...") time.Sleep(time.Second * 60) }
协程在使用cond时,首先需要对cond持有的锁进行加锁操作,然后调用Wait函数等待,后续操作会阻塞在Wait处;当主协程决定唤醒等待的协程时,它会使用Signal(随机唤醒一个等待的协程)或Broadcast(唤醒所有等待的协程)唤醒等待的协程。当某一协程被唤醒后,Wait函数会返回,此时需要解锁,之后便可以做后续的操作了;
实现细节:
cond的数据结构
type Cond struct { noCopy noCopy // L is held while observing or changing the condition L Locker notify notifyList checker copyChecker }
Cond结构体持有一把锁,这个锁用来做协程间的同步操作;notify是一个唤醒队列,所有调用过Wait方法的协程都会被加入到这个唤醒队列中
Wait函数
func (c *Cond) Wait() { c.checker.check() t := runtime_notifyListAdd(&c.notify) c.L.Unlock() runtime_notifyListWait(&c.notify, t) c.L.Lock() }
首先,当前协程会被加入到notifyList中,之后会解锁L,这是因为以便让别的协程可以获取到锁,做同样的操作(lock, wait, unlock)中的lock这一步;之后 runtime_notifyListWait
会阻塞,即所有调用过Wait函数的协程都会阻塞在这个地方;
之后若该协程被唤醒,那么 runtime_notifyListWait
会返回,此时又回重新给L加锁,然后第一个抢占到这个返回操作的协程,它的Wait操作真正返回了;这个协程的Wait函数外部,可能后续还会做一些需要互斥的操作,在这个协程做完所有操作后,按照规定它会调用Unlock解锁,这时别的协程的Wait函数才能真正的返回,做后续操作;
关于唤醒函数就比较简单了:
func (c *Cond) Signal() { c.checker.check() runtime_notifyListNotifyOne(&c.notify) } func (c *Cond) Broadcast() { c.checker.check() runtime_notifyListNotifyAll(&c.notify) }
从队列中唤醒即可
有疑问加站长微信联系(非本文作者)

Recommend
-
30
概述 cond是go语言sync提供的条件变量,通过cond可以让一系列的goroutine在触发某个条件时才被唤醒。每一个cond结构体都包含一个锁L。cond提供了三个方法: Signal:调用Signal之后可以唤醒单个goroutine。...
-
18
Indentation matters when reading Clojure code. It is the primary visual cue that helps the reader discern the code structure. Most Clojure code seen in the wild conforms to either the
-
7
Golang sync库--Cond MontyOak · 大约15小时之前 · 42 次点击 · 预计阅读时间 3 分钟 · 不到1分钟之前 开始浏览 ...
-
7
sync.Cond 条件变量是 Golang 标准库 sync 包中的一个常用类。sync.Cond 往往被用在一个或一组 goroutine 等待某个条件成立后唤醒这样的场景,例如常见的生产者消费者场景。 本文将基于
-
5
[Submitted on 2 May 2001] Freezing in Ising Ferromagnets Download PDF We investigate the final state...
-
6
在 Go 里有专门为同步通信而生的 channel,所以较少看到 sync.Cond 的使用。不过它也是并发控制手段里的一种,今天我们就来认识下它的相关实现...
-
4
Go 语言通过 go 关键字开启 goroutine 让开发者可以轻松地实现并发编程,而并发程序的有效运行,往往离不开 sync 包的保驾护航。目前,sync 包的赋能列表包括: sync.atomic 下的原子操作、sync.Map 并发安全 map、
-
5
sync.cond条件锁 | 修心修己 山不向我来,我便向它去,若一去不回,便一去不回。 Powered by xiusin | RSS...
-
10
pthread_mutex_t & pthread_cond_t 总结 一、多线程并发 1.1 多线程并发引起的问题 我们先来看如下代码: #in...
-
10
本文将介绍 Go 语言中的 sync.Cond 并发原语,包括 sync.Cond的基本使用方法、实现原理、使用注意事项以及常见的使用使用场景。能够更好地理解和应用 Cond 来实现 goroutine 之间的同步。 2. 基本使用
About Joyk
Aggregate valuable and interesting links.
Joyk means Joy of geeK