Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

关于 sync.Cond.Broadcast() 的讨论 #47

Open
chaffz opened this issue Jun 27, 2018 · 0 comments
Open

关于 sync.Cond.Broadcast() 的讨论 #47

chaffz opened this issue Jun 27, 2018 · 0 comments

Comments

@chaffz
Copy link

chaffz commented Jun 27, 2018

package main

import (
    "fmt"
    "sync"
    "time"
)

var locker = new(sync.Mutex)
var cond = sync.NewCond(locker)

func test(x int) {

    cond.L.Lock() // 获取锁
    cond.Wait()   // 等待通知  暂时阻塞
    fmt.Println(x)
    time.Sleep(time.Second * 1)
    cond.L.Unlock() // 释放锁,不释放的话将只会有一次输出
}
func main() {
    for i := 0; i < 40; i++ {
        go test(i)
    }
    fmt.Println("start all")
    cond.Broadcast() //  下发广播给所有等待的goroutine
    time.Sleep(time.Second * 60)
}

上面这个例子是从 chapter16/16.01.md 中 copy 下来,运行后,没有问题(或者说极少数人会遇到问题)
那接下来就做一行代码的修改

fmt.Println("start all") 注释掉

运行后会发现,程序没有输出了,或者说程序已经进入了 sleep 等待退出的状态了。

分析修改后的代码,在 Broadcast 执行时, Wait 操作还没来得及把通知加入 cond 的 notifyList 中,而例子中因为 fmt.Println("start all") 这一微弱的开销,使得 40 个 groutine 中已经有部分或者全部争取到了加入 notifyList 的机会。

顺着这个思路,猜测如果把 loop 次数增加,使得 loop 先执行的 groutine 有机会被加入 notifyList 中,我们修改为 1000、4000、10000等偿试。确实会如我们所料。命令如下:

go run main.go | wc -l

综上所述, 使得本人对 sync.Cond 的应用场景及正确姿势有了一些疑问,希望楼主及大伙一起探究。

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant