我的Go代码中有非常奇怪的行为。总体要点是,当我有
时for {
if messagesRecieved == l {
break
}
select {
case result := <-results:
newWords[result.index] = result.word
messagesRecieved += 1
default:
// fmt.Printf("messagesRecieved: %v\n", messagesRecieved)
if i != l {
request := Request{word: words[i], index: i, thesaurus_word: results}
requests <- request
i += 1
}
}
}
程序冻结并无法前进,但是当我取消注释fmt.Printf命令时,程序运行正常。您可以看到整个代码here。有谁知道是什么导致了这种行为?
答案 0 :(得分:2)
进入版本1.1.2(当前版本)仍然只有原始(自首次发布以来)goroutines的协作调度。编译器通过插入调度点来改进行为。从内存模型推断,它们是通道操作的旁边。另外还有一些众所周知但有意无证的地方,例如I / O发生的地方。最后一个解释了为什么取消注释fmt.Printf
会改变程序的行为。而且,顺便说一下,Go tip版本现在是一个抢占式调度程序。
您的代码让您的一个goroutine忙于完成默认的选择案例。由于没有其他调度点没有打印,没有其他goroutine有机会取得进展(假设默认GOMAXPROCS = 1)。
我建议以避免旋转(忙碌等待)的方式重写程序的逻辑。一种可能的方法是在默认情况下使用通道发送。作为使用缓冲通道的一个很好的副作用,人们可以免费获得一个简单的限制器。