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

Go Channel 写入超出其容量的数据

Go Channel 写入超出其容量的数据

Go
绝地无双 2022-10-24 09:59:35
package mainimport (    "fmt")func write(ch chan int) {    for i := 0; i < 5; i++ {        fmt.Println("avaliable", i)        ch <- i        fmt.Println("successfully wrote", i, "to ch")    }    close(ch)}func main() {    ch := make(chan int)    go write(ch)    for v := range ch {        fmt.Println("read value", v, "from ch")    }}输出avaliable 0successfully wrote 0 to chavaliable 1read value 0 from chread value 1 from chsuccessfully wrote 1 to chavaliable 2successfully wrote 2 to chavaliable 3read value 2 from chread value 3 from chsuccessfully wrote 3 to chavaliable 4successfully wrote 4 to chread value 4 from ch由于这是一个无缓冲的通道,它应该在数据写入它时立即阻塞,直到另一个 goroutine 从同一通道读取。但它接受的数据超出了它的能力。预期行为package mainimport (    "fmt"    "time")func write(ch chan int) {    for i := 0; i < 5; i++ {        fmt.Println("avaliable", i)        ch <- i        fmt.Println("successfully wrote", i, "to ch")    }    close(ch)}func main() {    ch := make(chan int)    go write(ch)    time.Sleep(time.Second)    for v := range ch {        fmt.Println("read value", v, "from ch")        time.Sleep(time.Second)    }}输出avaliable 0read value 0 from chsuccessfully wrote 0 to chavaliable 1read value 1 from chsuccessfully wrote 1 to chavaliable 2read value 2 from chsuccessfully wrote 2 to chavaliable 3read value 3 from chsuccessfully wrote 3 to chavaliable 4read value 4 from chsuccessfully wrote 4 to ch如果在整个代码中放置了一些计时器,以便主 goroutine 在每次迭代之前被阻塞,它就会按预期工作。
查看完整描述

2 回答

?
HUX布斯

TA贡献1876条经验 获得超6个赞

您无法从输出中推断出任何内容,因为“读取值”和“成功写入”Printfs 执行之间没有顺序保证。(在通道发送之前发生的“可用”Printf 和在相应通道接收之后发生的“读取值”Printf 之间存在一个,您可以看到输出中永远不会违反该顺序)。

通道没有缓冲任何东西,因为它没有缓冲;只是通道发送完成后,两个不同的 goroutine 以不确定的顺序运行。有时发送方先走并打印“成功写入”消息,有时接收方先走并打印“读取值”消息。没有一个“领先”超过一个值,因为它们仍然在通道发送上完全同步;他们只是在比赛之后立即打印他们的状态消息。

当您将 Sleep 调用添加到 main 时,它恰好使运行的 goroutinewrite在等待发送下一个值时总是被阻塞,而正在运行的 goroutinemain在调用时阻塞Sleep。当定时器超时时,主协程被唤醒,并立即发现它在通道上等待它的东西,抓住它,然后重新进入睡眠状态,然后write协程被唤醒。通过放慢速度,您已经让调度程序以一致的顺序运行事物(尽管这仍然部分是运气问题);没有睡眠,一切都尽可能快地运行,结果显然是随机的。


查看完整回答
反对 回复 2022-10-24
?
精慕HU

TA贡献1845条经验 获得超8个赞

如果是这样的话,“睡眠”版本的输出会更加混乱。

即使它们在某个点同步,您也不能期望两个独立线程的一致输出。


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

添加回答

举报

0/150
提交
取消
微信客服

购课补贴
联系客服咨询优惠详情

帮助反馈 APP下载

慕课网APP
您的移动学习伙伴

公众号

扫描二维码
关注慕课网微信公众号