01
介绍
在「Effective Go」并发章节讲到,“不要通过共享内存进行通信;而是通过通信共享内存”。由此表明 Golang 语言官方鼓励用户使用“通过通信共享内存”的方式并发编程。
但是,Golang 语言也在标准库 sync 包中提供了传统的同步原语。
我们应该选择哪种并发编程方式呢?Golang 语言官方也给了使用指南:
如表格所示,传递数据的所有权,分发工作任务和通信异步结果,这三种场景建议使用 Channel。缓存和状态,这两种场景建议使用 Mutex。
在 Golang 语言官方博客「The Go Memory Model」一文中,对 channel 的描述如下:
A send on a channel happens before the corresponding receive from that channel completes. A receive from an unbuffered channel happens before the send on that channel completes.
本文我们主要介绍一些关于 Channel 的使用方式。关于 Golang 语言 sync 包的同步原语和 Channel 的介绍,我们在之前的文章已经介绍过了,在此不再赘述,感兴趣的读者朋友可以按需翻阅。
02
无缓冲 channel
无缓冲 channel 可用于两个 goroutine 之间传递信号,比如以下示例:
顺序打印 1 至 100 的奇数和偶数:
阅读上面这段代码,我们使用一个无缓冲 channel 作为两个 goroutine 之间的信号传递的桥梁。
主子 goroutine 之间传递信号:
阅读上面这段代码,我们使用一个无缓冲 channel 作为主子 goroutine 之间的信号传递的桥梁。通过信号传递,主 goroutine 在子 goroutine 运行结束之后再退出。
03
有缓冲 channel
有缓冲 channel 可以用于解耦操作,模拟消息队列。“生产者”和“消费者”只需各自处理 channel,实现解耦。
解耦“生产者”和“消费者”:
阅读上面这段代码,我们使用一个有缓冲的 channel,将“生产者”和“消费者”做解耦操作。
04
超时操作和定时器
我们还可以通过 select 和 channel,实现超时操作和定时器。
超时操作:
阅读上面这段代码,我们通过 c1 和 c2 两个 channel,分别模拟出超时和未超时场景。
定时器:
阅读上面这段代码,我们定义一个打点器,每间隔 500ms 执行一次操作,当打点器 stop 时,通过一个无缓冲 channel 传递退出信号。
05
总结
本文我们介绍了一些关于 Channel 的使用方式,我们在阅读完本文后可以了解无缓冲 channel 作为信号传递的使用方式和有缓冲 channel 解耦操作的方式,以及 channel 与 select 配合使用的用法。