go - sleep 例行程序永远不会唤醒/永远被阻塞

标签 go goroutine

我的问题可以概括为以下代码段:

    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 sectionselect statement,它们可能可以帮助您更轻松地重构程序,并且更适合您。

关于go - sleep 例行程序永远不会唤醒/永远被阻塞,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59880479/

相关文章:

去运行/构建没有得到依赖

pointers - 结构初始化不当?

go - 避免goroutines之间双向通信的死锁

go - goroutines 和 Http 请求超时

amazon-web-services - 缺失区域 : could not find region configuration in golang and aws sns

go - []struct 中附加的不需要的类型

go - 为什么 goroutine 执行命令在运行之间是相同的

go - 管理动态 goroutine 池的最佳方式

go - 如何在CircleCI Go图像中使用Terraform

在 go 中解析 set-cookie header