英文:
Why is this code Undefined Behavior?
问题
这是一段Go代码。我的朋友告诉我这是UB(未定义行为)的代码。为什么呢?
英文:
var x int
done := false
go func() { x = f(...); done = true }
while done == false { }
This is a Go code piece. My fiend told me this is UB code. Why?
答案1
得分: 5
如在“为什么这个程序在我的系统上终止,但在playground上不终止?”中所解释的,
Go内存模型不能保证在goroutine中写入的值会被
main
程序观察到。
在go routine destruction部分的示例中也给出了类似错误的程序。
Go内存模型还在该部分明确指出了没有同步的忙等待是一种错误的习惯用法。
在你的情况下,不能保证goroutine中写入的值会被main
程序观察到。
在这里,你需要在goroutine中进行某种形式的同步,以确保done=true
在main
中的for
循环的某个迭代之前发生。
“while
”(在Go中不存在)应该被替换为一个通道,你在其中阻塞(等待通信)。
for {
<-c // 2
}
基于在main
中创建的通道(c := make(chan bool)
),并在goroutine中关闭(close(c)
)。
sync包提供了其他等待goroutine结束后再退出main的方法。
例如,参见Golang示例等待所有后台goroutine完成:
var w sync.WaitGroup
w.Add(1)
go func() {
// 做一些事情
w.Done()
}
w.Wait()
英文:
As explained in "Why does this program terminate on my system but not on playground?"
> The Go Memory Model does not guarantee that the value written to x in the goroutine will ever be observed by the main
program.
A similarly erroneous program is given as an example in the section on go routine destruction.
The Go Memory Model also specifically calls out busy waiting without synchronization as an incorrect idiom in this section.
(in your case, there is no guarantee that the value written to done
in the goroutine will ever be observed by the main
program)
Here, You need to do some kind of synchronization in the goroutine in order to guarantee that done=true
happens before one of the iterations of the for
loop in main
.
The "while
" (non-existent in Go) should be replaced by, for instance, a channel you block on (waiting for a communication)
for {
<-c // 2
}
Based on a channel (c := make(chan bool)
) created in main
, and closed (close(c)
) in the goroutine.
The sync package provides other means to wait for a gorountine to end before exiting main.
See for instance Golang Example Wait until all the background goroutine finish:
var w sync.WaitGroup
w.Add(1)
go func() {
// do something
w.Done()
}
w.Wait()
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论