睡眠去例行公事永远不会永远醒来/被阻止



我的问题可以总结为以下代码片段:

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"再也没有机会运行。经过一些研究,看起来这是因为go例程"2"占用了所有CPU。

我以前在 java 中做过类似的事情,线程"1"总是可以在大约 1 秒后唤醒。

我的问题是如何在 Go 中实现相同的行为?(我正在将最初用 Java 编写的套接字程序转移到 Go(

我也尝试过运行时。GOMAXPROCS(2(,但不起作用

Go例程对刚接触 Go 的人来说可能会产生许多令人惊讶的副作用。其中更重要的一个问题是空无限循环的问题。

按照 Go 调度程序的工作方式,每个函数调用都应该在调用开始时放置一个抢占点。这应该发生在您的fmt.Println("2")调用中,这意味着每次调用打印时,后台的调度程序都能够在任何给定时间移动正在运行的例程,增加 goroutine 的内存等。

在正常情况下,即使它不是理想的编写代码,这也应该足够了。鉴于您在评论中声明这不是您正在使用的实际代码,因此实际上无法回答为什么您的其他代码可能不起作用。

如果您有兴趣了解有关 go 调度程序如何工作的更多信息,我会推荐这篇超越抢占的文章,以及这些在较低级别涵盖调度器的文章。

我还建议浏览一下 Tour of Go 网站。虽然有些概念相当基本,但如果您了解工具箱中的所有工具,则可以执行一些非常复杂的事情。我特别推荐并发部分和 select 语句,它们可能会帮助您更轻松地重构程序,并且以更合适的方式进行重构。

最新更新