
//shared values are passed around on channels // 信號量. /* var sem = make(chan int, MaxOutstanding) func handle(r *Request) { sem <- 1 // Wait for active queue to drain. process(r) // May take a long time. <-sem // Done; enable next request to run. } func Serve(queue chan *Request) { for { req := <-queue go handle(req) // Don't wait for handle to finish. } } 一堆請求requests進入serve中,不停的給req.進行handle操作 每運行一個之前,都用這個公共的變量req來進行維護.信號量滿了就展廳handle新的, 每一個handle玩就會讓信號量+1,可以讓新的東西進來繼續跑. 這個代碼有bug,因為堵塞是在handle里面發生的,所以同時有無窮個請求打過來 的時候,還是會開啟所有的線程,cpu會被無限吃光. 所以就需要下面的讓堵塞發生給for循環上.直接在serve層面堵塞.這樣cpu就只能開 MaxOutstanding這么多的線程了. func Serve(queue chan *Request) { for req := range queue { sem <- 1 //因為信號量放這里,堵塞for循環,會讓cpu保證不會無窮耗盡! go func() { process(req) // Buggy; see explanation below. <-sem }() } } //下面處理for循環層面的變量問題,for循環里面的變量是共享內存的. 也就是 上面的代碼for循環中第一次循環體和第二次循環體內容同時跑的時候,他們 操作的是同一個req.這不是我們要的.所以在下面代碼中 go func(req *Request) 進行一次值拷貝,這樣就保證每一次for循環中操作的變量 都唯一了. func Serve(queue chan *Request) { for req := range queue { sem <- 1 go func(req *Request) { process(req) <-sem }(req) } } //當然下面這個req:=req 是go語言推薦的寫法,確實更加簡練. //當然也是一次值拷貝. func Serve(queue chan *Request) { for req := range queue { req := req // Create new instance of req for the goroutine. sem <- 1 go func() { process(req) <-sem }() } } */