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