[英]Golang http server blocks when starts a goroutine of infinite-loop
As i learned from golang docs, if i set runtime.GOMAXPROCS(8) with a cpu of 8 cores (intel i7), then start a goroutine of infinite-loop, other gorutines should not be blocked because there are engough threads and goprocs. 正如我从golang docs那里学到的,如果我用8个核心(intel i7)的cpu设置runtime.GOMAXPROCS(8),然后启动无限循环的goroutine,其他gorutines不应该被阻止,因为有很多线程和goprocs。 But this is not true when using net/http package, an infinite-loop goroutine will block http server after a few invocations.
但是当使用net / http包时,这不是真的,无限循环goroutine会在几次调用后阻塞http服务器。 Can anyone help to explain why ?
任何人都可以帮忙解释原因吗?
Server code: 服务器代码:
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)
}
}
Client code: 客户代码:
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()
}
}
}
Now i know why such emtpy loop block other goroutines, but why runtime.LockOSThread()
doesn't help either? 现在我知道为什么这样的emtpy循环阻止其他goroutines,但为什么
runtime.LockOSThread()
也无济于事?
func infiniteloop() {
// add LockOSThread will not help
runtime.LockOSThread()
for {
}
}
As http://golang.org/pkg/runtime/#LockOSThread mentioned, the empty loop should be executed in an standalone thread, and other goroutines should not be impacted by the busy loop. 正如http://golang.org/pkg/runtime/#LockOSThread所提到的,空循环应该在一个独立的线程中执行,而其他goroutine不应该受到busy循环的影响。 What's wrong in my understanding?
我的理解有什么不对?
The Go runtime's scheduler is not fully pre-emptive at this time . Go运行时的调度程序目前还没有完全先发制人 。 Go 1.2 improved matters by occasionally calling into the scheduler on function calls , but the infinite loops in your example have no function calls so this doesn't help.
通过在函数调用中偶尔调用调度程序来改进1.2改进的问题,但是示例中的无限循环没有函数调用,所以这没有帮助。
With an actual body to your infinite loop handlers, you may see better behaviour. 通过实体到无限循环处理程序,您可能会看到更好的行为。 Alternatively, a manual call to
runtime.Gosched
may help in cases like this. 或者,手动调用
runtime.Gosched
可能会有所帮助。
The scheduler might not be able to preempt such an empty "infinite" loop. 调度程序可能无法抢占这种空的“无限”循环。 The scheduler got better and better during the last release, maybe he should be good enough for such code;
调度程序在上一次发布期间变得越来越好,也许他应该对这些代码足够好; he definitely is good enough for real code.
他肯定对真正的代码足够好。 Just don't do such nonsense.
只是不要做这样的废话。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.