调用runtime.Goexit()来手动终止协程
goroutine作为Golang并发的核心,我们不仅要关注它们的创建和管理,当然还要关注如何合理的退出这些协程,不(合理)退出不然可能会造成阻塞、panic、程序行为异常、数据结果不正确等问题。
for-range是使用频率很高的结构,常用它来遍历数据,range能够感知channel的关闭,当channel被发送数据的协程关闭时,range就会结束
,接着退出for循环。
它在并发中的使用场景是:当协程只从1个channel读取数据,然后进行处理,处理后协程退出。下面这个示例程序,当in通道被关闭时,协程可自动退出。 gofunc(in<-chanint){ //Usingfor-rangetoexitgoroutine //rangehastheabilitytodetecttheclose/endofachannel forx:=rangein{ fmt.Printf("Process%d\n",x) } }(inCh)for-select也是使用频率很高的结构,select提供了多路复用的能力,所以for-select可以让函数具有持续多路处理多个channel的能力。但select没有感知channel的关闭,这引出了2个问题:
1)继续在关闭的通道上读,会读到通道传输数据类型的零值。
2)继续在关闭的通道上写,将会panic。问题2可使用的原则是,通道只由发送方关闭,接收方不可关闭,即某个写通道只由使用该select的协程关闭,select中就不存在继续在关闭的通道上写数据的问题。
第一种:如果某个通道关闭后,需要退出协程,直接return即可。示例代码中,该协程需要从in通道读数据,还需要定时打印已经处理的数量,有2件事要做,所有不能使用for-range,需要使用for-select,当in关闭时,ok=false,我们直接返回。
gofunc(){ //infor-selectusingoktoexitgoroutine for{ select{ casex,ok:=<-in: if!ok{ return } fmt.Printf("Process%d\n",x) processedCnt++ case<-t.C: fmt.Printf("Working,processedCnt=%d\n",processedCnt) } } }()第二种:如果某个通道关闭了,不再处理该通道,而是继续处理其他case,退出是等待所有的可读通道关闭。我们需要使用select的一个特征:select不会在nil的通道上进行等待。这种情况,把只读通道设置为nil即可解决。
gofunc(){ //infor-selectusingoktoexitgoroutine for{ select{ casex,ok:=<-in1: if!ok{ in1=nil } //Process casey,ok:=<-in2: if!ok{ in2=nil } //Process case<-t.C: fmt.Printf("Working,processedCnt=%d\n",processedCnt) } //Ifbothinchannelareclosed,goroutineexit ifin1==nil&&in2==nil{ return } } }()使用,ok来退出使用for-select协程,解决是当读入数据的通道关闭时,没数据读时程序的正常结束。想想下面这2种场景,,ok还能适用吗?
接收的协程要退出了,如果它直接退出,不告知发送协程,发送协程将阻塞。 启动了一个工作协程处理数据,如何通知它退出?使用一个专门的通道,发送退出的信号,可以解决这类问题。以第2个场景为例,协程入参包含一个停止通道stopCh,当stopCh被关闭,case<-stopCh会执行,直接返回即可。
当我启动了100个worker时,只要main()执行关闭stopCh,每一个worker都会都到信号,进而关闭。如果main()向stopCh发送100个数据,这种就低效了。
funcworker(stopCh<-chanstruct{}){ gofunc(){ deferfmt.Println("workerexit") //Usingstopchannelexplicitexit for{ select{ case<-stopCh: fmt.Println("Recvstopsignal") return case<-t.C: fmt.Println("Working.") } } }() return }本文内容总结:1.手动终止,2.1使用for-range退出,2.2使用,ok退出,2.3使用退出通道退出,总结:,
原文链接:https://www.cnblogs.com/peteremperor/p/14070230.html