2 回答
TA贡献1866条经验 获得超5个赞
你的结果是完全合理的。由于 goroutine 相互独立运行,您永远不会知道 goroutine 何时开始执行。只要行
m[2] = "Second Value"
执行后,它将反映在您的主要 go 例程中。
因此,当在程序的第一次和第二次打印之间执行上述行时,您会看到结果为
1-First Value
2-Second Value
3-Second Value
4-Second Value
当它不是你看到另一个。在第三次打印之前,您确保其他 go 例程已完成。
如果你稍微修改你的程序,只是为了更清除它
package main
import "fmt"
import "time"
func main() {
m := make(map[int]string)
m[2] = "First Value"
c := make(chan bool)
go func() {
m[2] = "Second Value"
c <- true
}()
time.Sleep(time.Second)
fmt.Printf("1-%s\n", m[2])
fmt.Printf("2-%s\n", m[2])
_ = <-c
fmt.Printf("3-%s\n", m[2])
fmt.Printf("4-%s\n", m[2])
}
Playground
您很可能会得到以下输出
1-Second Value
2-Second Value
3-Second Value
4-Second Value
希望能帮助到你。
TA贡献1856条经验 获得超17个赞
您的代码实际上只是确保第三次和第四次打印显示第二个值。当您将通道更改为缓冲区为 1 时,它并没有真正改变任何东西。
那么我们来看第一种情况。您有一个无缓冲的频道。您触发的 go 例程会更改地图的内容。但是您不知道调度程序何时会运行它。这就是为什么有时您会看到一个结果,而有时会看到另一个结果。call:_ = <-c
将确保 go 例程已经运行。因为这个调用会阻塞,直到 go 例程实际在通道上写了一些东西。这就是为什么您永远不会在最后 2 次打印中看到“第一个值”的原因。
当您使用缓冲通道时,唯一会改变的是 go 例程将在写入通道后立即退出。没有别的(在Effective Go上阅读)。
- 2 回答
- 0 关注
- 209 浏览
添加回答
举报