Go 睡眠程序永远不会醒来/永远被阻塞

Go 睡眠程序永远不会醒来/永远被阻塞,go,goroutine,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

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

    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

}
在那里,围棋1再也没有机会跑了。在做了一些研究之后,看起来是因为go例程2占用了所有的CPU

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

我的问题是如何在go中实现相同的行为?我正在将一个最初用Java编写的socket程序传输到go


我也尝试过runtime.GOMAXPROCS2,但没有成功

对于新手来说,Go例程可能会有很多令人惊讶的副作用。其中一个更重要的问题是空无限循环的问题

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

在正常情况下,即使它不是理想的编写代码,这应该足够了。考虑到您在评论中指出这不是您正在使用的实际代码,因此不可能真正回答为什么您的其他代码可能不起作用

如果您有兴趣了解更多关于go调度器如何工作的信息,我建议您阅读有关抢占的文章,以及在较低级别上介绍调度器的文章


我还建议大家浏览一下这个网站。虽然其中一些概念相当基本,但如果您了解工具箱中的所有工具,则可以执行一些非常复杂的操作。我特别推荐,和,它可能会帮助您更容易地重构程序,并且以更适合的方式进行重构

goroutine不是线程。在当前版本中,它们不是可抢占的。这样的紧密循环不会让其他goroutine运行。顺便说一句,在循环中使用fmt.Println不会阻止goroutine调度程序运行其他goroutine,因为这涉及IO操作。因此,在您的示例中,所有的goroutine都被安排好了,但是您的示例代码有无止境的循环,它们永远不会结束。请注意,Go中的socket程序无论如何都不应该有这样的代码,如果goroutine需要协调,那么时间就是答案。睡眠永远不是答案。最好说明实际的问题是什么。@user9607441:网络操作被阻塞了,所以除了消息之间的间隔之外,我看不出任何需要睡眠的原因。你描述的场景与你上面写的非常不同。无限循环本身不是问题,每个网络服务器定义都有一个循环;问题是,虽然网络操作只有在有数据时才会运行,但Println会立即继续。一般来说,如果您在某些代码上遇到问题,请发布这些代码,而不是一个模糊不清的类似示例。这个例子是如此精心设计,它保证与您在Go中使用socket编程时遇到的任何问题无关。