go条件变量sync.Cond的使用和思考

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/u010230794/article/details/82386312

源码采用1.9版本;sync包的Cond,条件变量;在我看来,主要是采用他的wait()方法,来控制被阻塞的go程何时去竞争锁;我暂且叫它“双开关控制”(欢迎大神斧正):
废话少说,来个小例子吧:

package main
import (
    "fmt"
    "sync"
    "time"
)

func main() {
    var lc = new(sync.Mutex)
    //这个locker 为啥传入一个引用?
    var cond = sync.NewCond(lc)
    for i := 0; i < 3; i++ {
        go func(x int) {
            cond.L.Lock()
            defer cond.L.Unlock()
            cond.Wait()
            fmt.Println(x)
        }(i)
    }
    //睡眠一会,确保下面的Signal()能通知到一个(难道可能通知不到?)
    time.Sleep(2*time.Second)
    cond.Signal()
    cond.Broadcast()
    time.Sleep(2*time.Second)
}

运行结果:

0
2
1

上面例子中有两个问题,我们带着问题,查看Cond的一个重要方法:

func (c *Cond) Wait() {
    //检查cond是否被拷贝
    c.checker.check()
    //将获得锁的那个go程加入等待队列
    t := runtime_notifyListAdd(&c.notify)
    //释放锁(可见调用之前要有c.L.lock)
    c.L.Unlock()
    //go程的等待队列等待唤醒,这个操作是阻塞的,除非本go程被唤醒
    runtime_notifyListWait(&c.notify, t)
    //外部记得释放
    c.L.Lock()
}

为啥传入一个引用?通过wait方法我看到c.L 的操作,如果不是指针变量,也就是发生锁得拷贝,将导致锁不统一,从而发生死锁;
难道可能通知不到?如果不等待至少一个go程加入等待队列,此时调用cond.Signal() 通知,是没有作用的;并且我们发现,go程加入等待队列,需要竞争锁,其实我也没有想明白,为啥要加锁,也许是等待队列的操作是线程不安全的。

猜你喜欢

转载自blog.csdn.net/u010230794/article/details/82386312