考虑这个程序:package mainimport "fmt"import "time"import "runtime"func main() { x := 0 go func() { time.Sleep(500 * time.Millisecond) x = 1 }() for x == 0 { runtime.Gosched() } fmt.Println("it works!")}为什么它在本地终止而不是在Playground上终止?我的程序的终止是否依赖于未定义的行为?
3 回答
慕慕森
TA贡献1856条经验 获得超17个赞
该代码没有提供太多保证。它几乎完全依赖于未定义行为的实现细节。
在大多数多线程系统中,不能保证一个没有障碍的线程中的更改会在另一个线程中看到。你有一个 goroutine,它可以在另一个处理器上运行,将一个值写入一个没有人保证读取的变量。
将for x == 0 {
可以很容易地重写for {
,因为从未有一个保证该变量的任何变化可能是可见的。
竞赛检测器也可能会报告此问题。你真的不应该期望这会起作用。如果你想要一个,sync.WaitGroup
你应该只使用一个,因为它可以跨线程正确协调。
DIEA
TA贡献1820条经验 获得超2个赞
Go Playground 使用了一种特殊的实现,time.Sleep
旨在防止单个程序垄断网站的后端资源。
正如这篇关于如何实现Playground 的文章中所述,调用 time.Sleep() 的 goroutine 被置于睡眠状态。操场后端等待直到所有其他 goroutine 被阻塞(否则会出现死锁),然后以最短的时间唤醒 goroutine。
在您的程序中,您有两个 goroutine:一个主要的,一个调用time.Sleep
. 由于主 goroutine 永远不会阻塞,因此time.Sleep
调用永远不会返回。程序继续运行,直到超过分配给它的 CPU 时间,然后终止。
- 3 回答
- 0 关注
- 219 浏览
添加回答
举报
0/150
提交
取消