控制并发有两种经典的方式,一种是waitgroup,另外一种就是context
func main() { var wg sync.waitgroup wg.add(2) go func() { time.sleep(2*time.second) fmt.println("1号完成") wg.done() }() go func() { time.sleep(2*time.second) fmt.println("2号完成") wg.done() }() wg.wait() fmt.println("好了,大家都干完了,放工") }
以上例子一定要等到两个goroutine同时做完才会全部完成,这种控制并发方式尤其适用于多个goroutine协同做一件事情的时候。
func main() { stop := make(chan bool) go func() { for { select { case <-stop: fmt.println("监控退出,停止了...") return default: fmt.println("goroutine监控中...") time.sleep(2 * time.second) } } }() time.sleep(10 * time.second) fmt.println("可以了,通知监控停止") stop<- true //为了检测监控过是否停止,如果没有监控输出,就表示停止了 time.sleep(5 * time.second) }
例子中我们通过select判断stop是否接受到值,如果接受到值就表示可以推出停止了,如果没有接受到,就会执行default里面的监控逻辑,继续监控,直到收到stop的通知 以上控制goroutine的方式在大多数情况下可以满足我们的使用,但是也存在很多局限性,比如有很多goroutiine,并且这些goroutine还衍生了其他goroutine,此时chan就比较困难解决这样的问题了
以上问题是存在的,比如一个网络请求request,每个request都需要开启一个goroutine做一些事情。所以我们需要一种可以跟踪goroutine的方案才可以达到控制的目的,go为我们提供了context
func main() { ctx, cancel := context.withcancel(context.background()) go watch(ctx,"【监控1】") go watch(ctx,"【监控2】") go watch(ctx,"【监控3】") time.sleep(10 * time.second) fmt.println("可以了,通知监控停止") cancel() //为了检测监控过是否停止,如果没有监控输出,就表示停止了 time.sleep(5 * time.second) } func watch(ctx context.context, name string) { for { select { case <-ctx.done(): fmt.println(name,"监控退出,停止了...") return default: fmt.println(name,"goroutine监控中...") time.sleep(2 * time.second) } } }
例子中启动了3个监控goroutine进行不断的监控,每一个都使用context进行跟踪,当我们使用cancel函数通知取消时候,这3个 goroutine都会被结束。所有基于这个context或者衍生出来的子context都会收到通知,这样就可以进行清理操作最终释放goroutine了
context是一个接口,具体的内容如下:
~go~
type context interface {
deadline() (deadline time.time, ok bool)
done() <-chan struct{}
err() error
value(key interface{}) interface{}
}
func withcancel(parent context) (ctx context, cancel cancelfunc) func withdeadline(parent context, deadline time.time) (context, cancelfunc) func withtimeout(parent context, timeout time.duration) (context, cancelfunc) func withvalue(parent context, key, val interface{}) context
这四个with函数,接收的都有一个partent参数,就是父context,我们要基于这个父context创建出子context的意思
如对本文有疑问, 点击进行留言回复!!
网友评论