Golang http服务器在启动无限循环的goroutine时阻塞

Golang http服务器在启动无限循环的goroutine时阻塞,http,go,block,goroutine,Http,Go,Block,Goroutine,正如我从golang docs中学到的,如果我将runtime.GOMAXPROCS(8)设置为8核cpu(intel i7),然后启动一个无限循环的goroutine,其他gorutine就不应该被阻塞,因为有engough线程和goprocs。但当使用net/http包时,情况并非如此,一个无限循环goroutine将在几次调用后阻塞http服务器。 有人能解释一下原因吗 如果我注释“go infinite loop”一行,在服务器之后启动客户端,客户端将输出1000个星号;但如果我启用go

正如我从golang docs中学到的,如果我将runtime.GOMAXPROCS(8)设置为8核cpu(intel i7),然后启动一个无限循环的goroutine,其他gorutine就不应该被阻塞,因为有engough线程和goprocs。但当使用net/http包时,情况并非如此,一个无限循环goroutine将在几次调用后阻塞http服务器。 有人能解释一下原因吗

  • 如果我注释“go infinite loop”一行,在服务器之后启动客户端,客户端将输出1000个星号;但如果我启用goroutine,客户端将在打印几个星号后阻塞
  • 我已经尝试在goroutine中添加runtime.LockOSThread(),但似乎不起作用
  • 我的环境:osx 10.10,go版本go1.3.1 darwin/amd64
  • 服务器代码:

    客户端代码:


    如前所述,空循环应在独立线程中执行,其他goroutine不应受到忙循环的影响。我的理解有什么问题?

    调度程序可能无法抢占这样一个空的“无限”循环。调度器在上一个版本中变得越来越好,也许他应该足够好,可以编写这样的代码;他绝对是足够好的真正的代码。别胡闹了

    Go运行时的调度程序。Go 1.2改进了问题,但是您的示例中的无限循环没有函数调用,因此这没有帮助


    使用无限循环处理程序的实际主体,您可能会看到更好的行为。或者,在这种情况下,手动调用可能会有所帮助。

    一个“无限”循环不是问题。这是一个繁忙的循环,只会烧坏CPU,这是个问题。@GrzegorzŻur您确定客户端可以打印所有1000个星号吗?我交叉编译了源文件,并在linux/amd64平台上运行它们。客户之前打印了大约150个星号halted@user922965我的错误,我运行它的临界线注释掉了。我重做了测试,它被阻塞了。我得到了同样的暂停,这是意外的,一定是调度程序的一个限制?可能会提交错误报告:)我使用go1.4beta1 linux/amd64版本运行代码,但它没有打印一个字符:-(我认为这是一个很好的问题。我又增加了一个关于LockOfThread的问题,你能给出更多的建议吗?也许这有助于准确描述你正在尝试做的事情。当然你在真实的程序中没有使用空无限循环,那么你到底想知道什么呢?我试图比较golang和java nio之间的http性能,不是吗这是一个边缘案例,一些核心被其他应用程序耗尽,无法被http服务器使用。您的链接解决了我的问题。实际上,我只是想知道为什么“LockOSThread”不起作用,请尝试了解golang scheduler的更多信息。我不确定
    LockOSThread
    是否实际分配了另一个线程来运行Go code。如果没有,那么在这里就没有任何帮助。如果你想尝试减少应用程序运行的内核数量以进行测试,也许可以看看你的操作系统的CPU亲和性在Linux上,
    taskset
    实用程序可能会起到作用。
    package main
    
    import (
        "fmt"
        "log"
        "net/http"
        "runtime"
    )
    
    func myHandler(w http.ResponseWriter, req *http.Request) {
        w.Write([]byte("hello"))
    }
    
    func infiniteloop() {
        for {
    
        }
    }
    
    func main() {
        // set max procs for multi-thread executing
        runtime.GOMAXPROCS(runtime.NumCPU())
    
        // print GOMAXPROCS=8 on my computer
        fmt.Println("GOMAXPROCS=", runtime.GOMAXPROCS(-1))
        http.Handle("/", http.HandlerFunc(myHandler))
    
        // uncomment below line cause server block after some requests 
        // go infiniteloop()
        if err := http.ListenAndServe(":8280", nil); err != nil {
            log.Fatal(err)
        }
    }
    
    package main
    import (
        "fmt"
        "net/http"
    )
    
    func getOnce() {
        if resp, err := http.Get("http://localhost:8280"); err != nil {
            fmt.Println(err)
            return
        } else {
            defer func() {
                if err := resp.Body.Close(); err != nil {
                    fmt.Println(err)
                }
            }()
            if resp.StatusCode != 200 {
                fmt.Println("error codde:", resp.StatusCode)
                return
            } else {
                fmt.Print("*")
    
            }
        }
    }
    
    func main() {
        for i := 1; i < 1000; i++ {
            getOnce()
            if i%50 == 0 {
                fmt.Println()
            }
        }
    
    }