美文网首页golang成长记
goland cond数据结构学习

goland cond数据结构学习

作者: Tim_SSS | 来源:发表于2018-08-21 16:31 被阅读0次

    1、cond结构介绍

    // Cond implements a condition variable, a rendezvous point
    // for goroutines waiting for or announcing the occurrence
    // of an event.
    // Cond结构实现一个条件变量和约定指针,为了等待协程或者通知一个事件的发生。
    // Each Cond has an associated Locker L (often a *Mutex or *RWMutex),
    // which must be held when changing the condition and
    // when calling the Wait method.
    // 每一个cond都有一个与之关联Locker L的锁(通常是读锁或者读写锁)
    // 当条件改变条件和调用Wait方法时,这个锁是锁住的。
    // A Cond must not be copied after first use.
    // 这个Cond变量,在初始化之后,不能再被复制。
    type Cond struct {
        noCopy noCopy
        // L is held while observing or changing the condition
        // 当状态一直是改变或者是观察的状态时,L将被锁住
           L Locker
    
        notify  notifyList  // 事件通知列表
        checker copyChecker   // 检查变量是否被copy
    }
    

    2、cond方法介绍

    // NewCond returns a new Cond with Locker l.
    // 实例化一个带有Locker的Cond变量
    func NewCond(l Locker) *Cond {
        return &Cond{L: l}
    }
    
    // Wait atomically unlocks c.L and suspends execution
    // of the calling goroutine. After later resuming execution,
    // Wait locks c.L before returning. Unlike in other systems,
    // Wait cannot return unless awoken by Broadcast or Signal.
    // 等待释放锁和暂缓调用这个协程,在恢复执行之后,wait将一直锁住,
    //这点不像其他操作系统,如果不调用Broadcast或者Signal, Wait将不返回
    // Because c.L is not locked when Wait first resumes, the caller
    // typically cannot assume that the condition is true when
    // Wait returns. Instead, the caller should Wait in a loop:
    // 因为Wait第一次恢复时,c.L是不被锁住的;当Wait返回时,调用者通常不认为这是真的
    // 相反,调用者,应该在循环中等待。
    //    c.L.Lock()
    //    for !condition() {
    //        c.Wait()
    //    }
    //    ... make use of condition ...
    //    c.L.Unlock()
    //
    func (c *Cond) Wait() {
        c.checker.check()
        t := runtime_notifyListAdd(&c.notify)
        c.L.Unlock()
        runtime_notifyListWait(&c.notify, t)
        c.L.Lock()
    }
    
    // Signal wakes one goroutine waiting on c, if there is any.
    // Signal 唤醒一个作用在c上等待的协程,无论是哪一个。
    // It is allowed but not required for the caller to hold c.L
    // during the call.
    // 在调用期间,c.L 是不一定要持有这个c.L
    func (c *Cond) Signal() {
        c.checker.check()
        runtime_notifyListNotifyOne(&c.notify)
    }
    
    // Broadcast wakes all goroutines waiting on c.
    // Broadcast 唤醒所有作用于c上而等待的协程。
    // It is allowed but not required for the caller to hold c.L
    // during the call.
    func (c *Cond) Broadcast() {
        c.checker.check()
        runtime_notifyListNotifyAll(&c.notify)
    }
    

    3、代码示例

    package main
    
    import (
        "sync"
        "fmt"
        "time"
    )
    
    var locker = new(sync.Mutex)
    var cond = sync.NewCond(locker)
    func main()  {
        for i:=0; i < 5; i++ {
            go func(x int) {
                cond.L.Lock() // wait 前,必须要先加锁
                defer cond.L.Unlock()
                cond.Wait()
                fmt.Println(x)
                time.Sleep(time.Second * 1)
            }(i)
        }
        time.Sleep(time.Second*1)
        fmt.Println("Signal....")
        cond.Signal() // 下发一个通知给已经获取锁的goroutine
        time.Sleep(time.Second * 3)
        cond.Signal() // 3 秒之后,下发一个通知给已经获取锁的goroutine
        time.Sleep(time.Second *3)
        cond.Broadcast() // 3 秒
        fmt.Println("Broadcast...")
        time.Sleep(time.Second * 60)
    }
    
    

    5、应用场景

    • 限流器

    参考:类库dropbox中,rate_limiter.go

    相关文章

      网友评论

        本文标题:goland cond数据结构学习

        本文链接:https://www.haomeiwen.com/subject/ktxjiftx.html