前言
在 Go 里有专门为同步通信而生的 channel,所以较少看到 sync.Cond 的应用。不过它也是并发管制伎俩里的一种,明天咱们就来意识下它的相干实现,加深对同步机制的使用。
sync.Cond
sync.Cond 提供了三个办法:Wait()、Signal()、Broadcast(),它们的用法如下:
- Wait():阻塞以后的 goroutine,期待唤起。
- Signal():唤起一个阻塞的 goroutine。
- Broadcast():唤起所有阻塞的 goroutine。
通过下面的办法形容,咱们就能够简略的实现一个 工作池 性能:先批量的创立 goroutine,而后调用 sync.Cond 的 Wait() 办法让其阻塞的期待。
当有一个工作到来时,则通过 Signal() 唤起刚刚在阻塞的某一个 goroutine,去执行工作。
通过工作池性能,咱们发现 sync.Cond 的使用很简略,但 Go 官网并不举荐咱们应用 sync.Cond 来实现 协程间的同步通信。
因为它并不合乎 Go 官网 “通过通信来共享内存” 的设计思维,当场景简单时,则会耦合各个业务性能。
sync.Cond 源码剖析
咱们来看下 sync.Cond 的构造体,代码在 /sr/sync/cond.go 下:
type Cond struct {
noCopy noCopy // 不可复制
L Locker // 锁
notify notifyList // 告诉唤起列表
checker copyChecker // 复制检测
}
能够看到 Cond 上有 notify 列表,而这正是保护了须要唤起的 goroutine 列表。
当咱们调用 Wait() 办法的时候就会保护以后 goroutine 到对应的 notifyList 里:
func (c *Cond) Wait() {c.checker.check()
t := runtime_notifyListAdd(&c.notify) // 将以后 goroutine 增加到 notifyList 里
c.L.Unlock()
runtime_notifyListWait(&c.notify, t) // 阻塞期待
c.L.Lock()}
当有其余协程调用了 Signal 或 Broadcast 办法时,则会通过 runtime_notifyListNotifyOne
或runtime_notifyListNotifyAll
办法来唤起一个或多个 goroutine。
其余同步形式的实现
后面提到到 sync.Cond 并不被举荐作为协同通信伎俩,那如果要实现它的单播、播送成果,该怎么弄呢?
其实也很简略,如果咱们要实现单播成果,那么只须要通过阻塞的监听 channel 信号即可。
如果要实现播送唤起成果,只须要利用 context 的链式勾销个性,也能达到该成果。
感兴趣的敌人能够搜一搜公众号「阅新技术」,关注更多的推送文章。
能够的话,就顺便点个赞、留个言、分享下,感激各位反对!
阅新技术,浏览更多的新常识。