我对GoLang世界很陌生,并且正在尝试goroutines/频道。据我所知,渠道是戈鲁丁之间的双向沟通方式。如果我们创建一个长度为 0 的通道,它应该是一个同步通道,它表示除非某些 goroutine(即使用者)从通道读取值,否则生产者将无法前进。我尝试了下面的示例来测试这一点,但我没有得到预期的结果。package mainimport ( "fmt" "time")var done = make(chan bool)var msgs = make(chan int)func produce() { for i := 0; i < 40; i++ { //fmt.Println("sending") fmt.Println("Produced: ", i) msgs <- i //fmt.Println("Channel size is: ", len(msgs)) } fmt.Println("Before closing channel") close(msgs) fmt.Println("Before passing true to done") }func consume() { for msg := range msgs { //fmt.Println("Going to take one, Channel size is: ", len(msgs)) fmt.Println("Consumer: ", msg) time.Sleep(100 * time.Millisecond) } done <- true }func main() { go produce() go consume() <-done fmt.Println("After calling DONE")}输出:Produced: 0Produced: 1Consumer: 0Consumer: 1Produced: 2Consumer: 2...我期望输出Produced: 0Consumer: 0Produced: 1Consumer: 1Produced: 2Consumer: 2请帮我在这里指出我做错了什么?
1 回答
子衿沉夜
TA贡献1828条经验 获得超3个赞
(无缓冲)通道读取/写入将按照您期望的顺序进行:一次写入;一读;一写;一次阅读等。
但是,生产者/消费者 goroutines 中的调用是不同步的 - 因此,生产者可以在 之前将其功能放入调度程序中。fmt.Println
fmt.Println
consumer
由于睡眠 - 它自愿向调度程序提供提示,让其他goroutines跑在它前面。因此,最有可能总是在醒来之前进行第二次运行。consumer
producer
fmt.Println
consumer
如果你把睡眠移到gooutine,你可以看到你在操场上的预期行为:https://play.golang.org/p/5x9_yyUaMiJ - 但是你不应该依赖这些计时技巧。如果要确保一个函数相对于另一个 goroutine 的执行顺序,这些任务也必须同步。通过通道读取/写入 - 只有读取/写入保证是安全的和顺序的。producer
- 1 回答
- 0 关注
- 75 浏览
添加回答
举报
0/150
提交
取消