package mainimport "runtime"func main() {var ch = make(chan int, 100)go func() {for i := 0; i < 100; i++ {ch <- 1if i == 88 {runtime.GC()}}}()for {// the wrong partif len(ch) == 100 {sum := 0itemNum := len(ch)for i := 0; i < itemNum; i++ {sum += <-ch}if sum == itemNum {return}}}}

可以看到gcwaiting = 1
以上代码,会导致程序hang住,因为在 for 循环中没有函数调用的话,编译器不会插入调度代码,所以这个执行 for 循环的 goroutine 没有办法被调出,而在循环期间碰到 gc,那么就会卡在 gcwaiting 阶段,并且整个进程永远 hang 死在这个循环上。并不再对外响应。
稍做改动,在for中调用一个函数,这段程序将不会出现问题
package mainimport ("fmt""runtime")func main() {var ch = make(chan int, 100)go func() {for i := 0; i < 100; i++ {ch <- 1if i == 88 {runtime.GC()}}}()for {fmt.Println("1--------------------------------1")if len(ch) == 100 {sum := 0itemNum := len(ch)for i := 0; i < itemNum; i++ {sum += <-ch}if sum == itemNum {return}}}}
来一个http的例子:
package mainimport ("fmt""io""log""net/http""runtime""time")func main() {runtime.GOMAXPROCS(runtime.NumCPU())go server()go printNum()var i = 1for {// will block here, and never go outi++}fmt.Println("for loop end")time.Sleep(time.Second * 3600)}func printNum() {i := 0for {i++}}func HelloServer(w http.ResponseWriter, req *http.Request) {io.WriteString(w, "hello, world!\n")}func server() {http.HandleFunc("/", HelloServer)err := http.ListenAndServe(":12345", nil)if err != nil {log.Fatal("ListenAndServe: ", err)}}
在main中也是有一个for循环,运行几秒,在浏览器上输入url,第一次没问题,多试几次总有一次被卡住。导致代码hang住,原因也是上面提到过的
