关于go:条件变量-Cond

35次阅读

共计 1825 个字符,预计需要花费 5 分钟才能阅读完成。

条件变量 Cond

Go 规范库提供 Cond 原语的目标是,为期待 / 告诉场景下的并发问题提供反对。Cond 通
常利用于期待某个条件的一组 goroutine,等条件变为 true 的时候,其中一个 goroutine
或者所有的 goroutine 都会被唤醒执行。

顾名思义,Cond 是和某个条件相干,这个条件须要一组 goroutine 合作共同完成,在条
件还没有满足的时候,所有期待这个条件的 goroutine 都会被阻塞住,只有这一组
goroutine 通过合作达到了这个条件,期待的 goroutine 才可能持续进行上来。
那这里期待的条件是什么呢?期待的条件,能够是某个变量达到了某个阈值或者某个工夫
点,也能够是一组变量别离都达到了某个阈值,还能够是某个对象的状态满足了特定的条
件。总结来讲,期待的条件是一种能够用来计算结果是 true 还是 false 的条件

应用 cond

func NeWCond(l Locker) *Cond
func (c *Cond) Broadcast()
func (c *Cond) Signal()
func (c *Cond) Wait()

首先,Cond 关联的 Locker 实例能够通过 c.L 拜访,它外部保护着一个先入先出的期待队
列。

Signal 办法 ,容许调用者 Caller 唤醒一个期待此 Cond 的 goroutine。如果此时没有等
待的 goroutine,显然无需告诉 waiter;如果 Cond 期待队列中有一个或者多个期待的
goroutine,则须要从期待队列中移除第一个 goroutine 并把它唤醒

调用 Signal 办法时,不强求你肯定要持有 c.L 的锁。

Broadcast 办法 ,容许调用者 Caller 唤醒所有期待此 Cond 的 goroutine。如果此时没有
期待的 goroutine,显然无需告诉 waiter;如果 Cond 期待队列中有一个或者多个期待的
goroutine,则清空所有期待的 goroutine,并全副唤醒

调用 Broadcast 办法时,不强求你肯定持有 c.L 的锁。

Wait 办法,会把调用者 Caller 放入 Cond 的期待队列中并阻塞,直到被 Signal 或者
Broadcast 的办法从期待队列中移除并唤醒。

调用 Wait 办法时必须要持有 c.L 的锁。

Cond 构造体

规范库中的 Cond 并发原语初始化的时候,须要关联一个 Locker 接口的实例,个别咱们
应用 Mutex 或者 RWMutex。

type Cond struct {
    // 能够将 noCopy 增加到第一次应用后不得复制的构造中
    noCopy noCopy

    // L is held while observing or changing the condition
    // 当察看或者批改期待条件的时候须要加锁
    L Locker
    
    // 期待队列
    notify  notifyList
    // copyChecker 是一个辅助构造,能够在运行时查看 Cond 是否被复制应用
    checker copyChecker
}

NewCond

// NewCond returns a new Cond with Locker l.
func NewCond(l Locker) *Cond {return &Cond{L: l}
}

Wait

Wait 把调用者退出到期待队列时会开释锁,在被唤醒之后还会申请锁。在阻塞休眠期间,
调用者是不持有锁的,这样能让其余 goroutine 有机会查看或者更新期待变量。

func (c *Cond) Wait() {c.checker.check()
    t := runtime_notifyListAdd(&c.notify)
    c.L.Unlock()
    runtime_notifyListWait(&c.notify, t)
    c.L.Lock()}

cond.Wait 办法的实现是,把以后调用者退出到 notify 队列之中后会开释锁(如果不开释锁,其余 Wait 的调用者就没有机会退出到 notify 队列中了),而后始终期待;等调用者被唤醒之后,又会去争抢这把锁。如果调用 Wait 之前不加锁的话,就有可能 Unlock 一个未加锁的 Locker。所以切记,调用 cond.Wait 办法之前肯定要加锁

Signal

func (c *Cond) Signal() {c.checker.check()
    runtime_notifyListNotifyOne(&c.notify)
}

Broadcast

func (c *Cond) Broadcast() {c.checker.check()
    runtime_notifyListNotifyAll(&c.notify)
}

正文完
 0