乐趣区

关于golang:golang-系列syncCond-机制

前言

在 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_notifyListNotifyOneruntime_notifyListNotifyAll办法来唤起一个或多个 goroutine。

其余同步形式的实现

后面提到到 sync.Cond 并不被举荐作为协同通信伎俩,那如果要实现它的单播、播送成果,该怎么弄呢?

其实也很简略,如果咱们要实现单播成果,那么只须要通过阻塞的监听 channel 信号即可。

如果要实现播送唤起成果,只须要利用 context 的链式勾销个性,也能达到该成果。


感兴趣的敌人能够搜一搜公众号「阅新技术」,关注更多的推送文章。
能够的话,就顺便点个赞、留个言、分享下,感激各位反对!
阅新技术,浏览更多的新常识。

退出移动版