为了账号安全,请及时绑定邮箱和手机立即绑定

无缓冲信道无法同步工作

无缓冲信道无法同步工作

Go
素胚勾勒不出你 2022-08-24 16:15:39
我对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.Printlnfmt.Printlnconsumer

由于睡眠 - 它自愿向调度程序提供提示,让其他goroutines跑在它前面。因此,最有可能总是在醒来之前进行第二次运行。consumerproducerfmt.Printlnconsumer

如果你把睡眠移到gooutine,你可以看到你在操场上的预期行为:https://play.golang.org/p/5x9_yyUaMiJ - 但是你不应该依赖这些计时技巧。如果要确保一个函数相对于另一个 goroutine 的执行顺序,这些任务也必须同步。通过通道读取/写入 - 只有读取/写入保证是安全的和顺序的。producer


查看完整回答
反对 回复 2022-08-24
  • 1 回答
  • 0 关注
  • 75 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信