我的问题可以概括为以下代码段:
package main
import (
"fmt"
"time"
)
func main() {
done := make(chan int)
done2 := make(chan int)
go func() {
for {
fmt.Println("1")
time.Sleep(time.Duration(1) * time.Second)
}
done <- 1
}()
go func() {
for {
fmt.Println("2")
}
done2 <- 1
}()
<- done
<- done2
}
go例程“1”永远不会再有机会运行。经过研究后,看起来好像是因为例程“2”占用了所有CPU。
我之前在Java中做过类似的事情,线程“1”总是可以在大约1秒后唤醒。
我的问题是我如何在go中实现相同的行为?(我正在将最初用Java编写的套接字程序转移到Go中)
我也尝试过runtime.GOMAXPROCS(2),但是没有用
最佳答案
Go新手的Go例程可能会产生许多令人惊讶的副作用。其中更重要的一个是空无限循环的问题。
Go调度程序的工作方式是,每个函数调用都应在调用开始处获得一个抢占点。这应该在您的fmt.Println("2")
调用中发生,这意味着每次调用打印时,后台的调度程序都可以在任何给定时间移动正在运行的例程,增加goroutine的内存等。
在正常情况下,即使不是理想的书面代码,也应该足够了。鉴于您已在注释中指出这不是您正在使用的实际代码,因此实际上不可能回答为什么其他代码可能无法工作。
如果您有兴趣了解有关go调度程序如何工作的更多信息,我建议您优先考虑this文章,该文章超越了抢占,而these文章涵盖了较低级别的调度程序。
我还建议您浏览Tour of Go网站。尽管其中一些概念是非常基本的,但是如果您了解工具箱中的所有工具,则可以做一些非常复杂的事情。我特别推荐concurrency section和select statement,它们可能可以帮助您更轻松地重构程序,并且更适合您。
关于go - sleep 例行程序永远不会唤醒/永远被阻塞,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59880479/