//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 }() } } */