一个发送者,N 个接收者¶

关键问题是,发送者如何知道呢?

Go 语言本身没有提供类似的函数,同时上一节,咱们也探讨了,使用 recover panic 的方式封装函数,同样会有数据竞争的问题。

语言层面不可行,那么就由开发者约定协议。

  • 通道应当由唯一发送者关闭

  • 若没有唯一发送者,则需要加“管理角色”的通道

第一点很好理解:当只有一个发送者时,他自己本身肯定是知道通道是否关闭,就不用再判断是否关闭了,自己想关闭就关闭,完全没事。

可要是没有唯一发送者呢?

这又要分两种情况了。

  1. 多个发送者,一个接收者

  2. 多个发送者,多个接收者

无论哪种场景,都会有数据竞争的问题。

上面我也说了,对于没有唯一发送者的方案就是加一个 “管理角色” 的通道。

为了方便解释,我将通道分为两种:

  1. 业务通道:承载数据,用于多个协程间共享数据

  2. 管理通道:仅为了标记业务通道是否关闭而存在

因此管理通道需要满足两个条件:

第一个条件:具备广播功能

那只能是无缓冲通道(关闭后,所有 read 该通道的所有协程,都能明确的知道该通道已关闭)。

  • 当该管理通道关闭了,说明业务通道也关闭了。

  • 当该管理通道阻塞了,说明业务通道还没关闭。

第二个条件:有唯一发送者

这个开发者非常容易实现:

  • 对于多个发送者,一个接收者的场景,业务通道的这个接收者,就可以充当管理通道的 唯一发送者

  • 对于多个发送者,多个接收者的场景,就需要再单独开启一个媒介协程做 唯一发送者

针对这两个场景,这边分别举个例子