正如我从golang docs那里学到的,如果我用8个核心(intel i7)的cpu设置runtime.GOMAXPROCS(8),那么启动一个无限循环的goroutine,其他的gorutines不应该被阻塞,因为有很多线程和goprocs。但是当使用net / http包时,这不是真的,无限循环goroutine会在几次调用后阻塞http服务器。 任何人都可以帮忙解释原因吗?
服务器代码:
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()
}
}
}
现在我知道为什么这样的emtpy循环会阻止其他goroutines,但为什么runtime.LockOSThread()
也没有帮助?
func infiniteloop() {
// add LockOSThread will not help
runtime.LockOSThread()
for {
}
}
如上所述http://golang.org/pkg/runtime/#LockOSThread,空循环应在独立线程中执行,其他goroutine不应受busy循环的影响。我的理解有什么不对?
答案 0 :(得分:3)
Go运行时的调度程序is not fully pre-emptive at this time。去1.2改进了问题by occasionally calling into the scheduler on function calls,但是你的例子中的无限循环没有函数调用,所以这没有帮助。
对于无限循环处理程序的实际正文,您可能会看到更好的行为。或者,手动拨打runtime.Gosched
可能会对此类情况有所帮助。
答案 1 :(得分:1)
调度程序可能无法抢占这样一个空的“无限”循环。调度程序在上一次发布期间变得越来越好,也许他应该对这样的代码足够好;他肯定对真正的代码足够好。只是不要做这样的废话。