Golang中channel的关闭和广播

Flutter、Golang、Python、编译原理、算法、Chrome原理学习系列文章抢先看请关注【码农帮派】

【Golang学习系列文章,请扫二维码】

 

先来看一段代码:

上面的代码中,数据的生产者和数据的接收者分别在两个协程中,通过Golang的CSP机制,通过channel发送/接收数据。

 

这段代码有一些问题:dataProducer和dataReceiver通过channel发送数据的时候,需要事先约定好发送/接收的数量,以此保证数据沟通的完整性,那么有没有更松的耦合方式呢?

 

我们可以约定一个特殊的数据标记(比如-1),当数据放完的时候,dataProducer就往channel中放入-1,表示数据已经发送完毕,但要是我们有好几个数据接收者,那么我们就需要放入很多个结束标记,这样显然也不友好。

 

最合适的方式是,当dataProducer发送完数据之后,关闭channel,而dataReceivers在从channel中获取数据的时候,同时判断channel的状态,要是channel已关闭,说明数据发送完毕。

 

dataProducer在发送完数据之后关闭channel:

 

对于消息接收者,要是channel被关闭,而消息接收者还在channel上接收数据,那么channel会立即返回channel消息类型的零值(上面的channel发送的int类型的消息,零值为0):

上面的代码中,dataProducer向channel中放入了5个消息之后就关闭了通道,而dataReceiver持续从channel中获取了7个消息,从打印结果可以看到,channel关闭之后,继续从channel读取消息程序并不会抛出异常,会立即返回通道消息的零值(int的零值为0)。

 

【注意】从已经关闭的channel读取数据并不会导致程序抛出异常,但是向已经关闭的channel中放入消息,会抛出panic异常。

 

dataReceivers在从channel中阻塞读取消息的时候,其实channel会返回两个数据,其中第二个数据可以用来判断channel当前时候处于关闭状态:

【注意】上面的代码中,ok是一个bool值,ok为true表示当前channel处于激活状态,ok为false的时候说明channel已经被关闭了,这时我们就没有必须继续监听channel的消息了。

 

【总结】

  • 向已经关闭的channel中发送消息,会导致panic;

  • msg, ok <- ch; ok为bool值,ok为true表示正常接收,ok为false的时候,表示channel已经关闭;

  • 所有channel接收者都会在channel关闭的时候,立刻从channel中返回上述的ok为false,此时的msg为消息数据类型的零值。这种机制常被用来向多个订阅者发送关闭消息。

 

下面利用channel的广播机制实现任务取消:

我们启动5个协程,协程内部通过channel发送消息,来判断什么时候取消当前协程任务:

上面的代码中,TestCancel中首先启动了5个协程,每个协程中每隔10毫秒判断一次是否应该取消协程任务,isCanceled方法中使用多路选择机制从channel中读取关闭消息,cancelChan一直处于阻塞状态,一旦有消息从cancelChan中发送,就会触发isCanceled函数返回true,是的协程任务取消。

 

接下来我们来看cancel函数中的方法如何完成。由上面的解析可知。cancelChan中只要有消息发出,任务就会被取消。

 

尝试在cancel函数中发送消息:

从上面的代码可以看到,只有一个协程被取消了,这是因为cancel函数中,向cancelChan发送了一个消息,可以被isCanceled函数消耗一次,取消掉一个协程的任务。要是我们要通知所有的协程取消任务,就需要知道总共有多少个协程,然后发送多少条消息,这样会导致代码耦合性大。

 

我们可以使用channel被关闭时,阻塞等待该channel的所有接收者都会立即返回的特点,进行多协程任务的取消:

通过close关闭cancelChan,实现了所有接听者的消息发送。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值