Go语言带缓冲的通道实现

作者:zx 时间:2024-02-08 18:34:13 

Go语言中有缓冲的通道(buffered channel)是一种在被接收前能存储一个或者多个值的通道。这种类型的通道并不强制要求 goroutine 之间必须同时完成发送和接收。通道会阻塞发送和接收动作的条件也会不同。只有在通道中没有要接收的值时,接收动作才会阻塞。只有在通道没有可用缓冲区容纳被发送的值时,发送动作才会阻塞。

这导致有缓冲的通道和无缓冲的通道之间的一个很大的不同:无缓冲的通道保证进行发送和接收的 goroutine 会在同一时间进行数据交换;有缓冲的通道没有这种保证。

在无缓冲通道的基础上,为通道增加一个有限大小的存储空间形成带缓冲通道。带缓冲通道在发送时无需等待接收方接收即可完成发送过程,并且不会发生阻塞,只有当存储空间满时才会发生阻塞。同理,如果缓冲通道中有数据,接收时将不会发生阻塞,直到通道中没有数据可读时,通道将会再度阻塞。

无缓冲通道保证收发过程同步。无缓冲收发过程类似于快递员给你电话让你下楼取快递,整个递交快递的过程是同步发生的,你和快递员不见不散。但这样做快递员就必须等待所有人下楼完成操作后才能完成所有投递工作。如果快递员将快递放入快递柜中,并通知用户来取,快递员和用户就成了异步收发过程,效率可以有明显的提升。带缓冲的通道就是这样的一个“快递柜”。

创建带缓冲通道

如何创建带缓冲的通道呢?参见如下代码:

通道实例 := make(chan 通道类型, 缓冲大小)

  • 通道类型:和无缓冲通道用法一致,影响通道发送和接收的数据类型。

  • 缓冲大小:决定通道最多可以保存的元素数量。

  • 通道实例:被创建出的通道实例。

下面通过一个例子中来理解带缓冲通道的用法,参见下面的代码:


package main
import "fmt"
func main() {
   // 创建一个3个元素缓冲大小的整型通道
   ch := make(chan int, 3)
   // 查看当前通道的大小
   fmt.Println(len(ch))
   // 发送3个整型元素到通道
   ch <- 1
   ch <- 2
   ch <- 3
   // 查看当前通道的大小
   fmt.Println(len(ch))
}

代码输出如下:
0
3

代码说明如下:

  • 第 8 行,创建一个带有 3 个元素缓冲大小的整型类型的通道。

  • 第 11 行,查看当前通道的大小。带缓冲的通道在创建完成时,内部的元素是空的,因此使用 len() 获取到的返回值为 0。

  • 第 14~16 行,发送 3 个整型元素到通道。因为使用了缓冲通道。即便没有 goroutine 接收,发送者也不会发生阻塞。

  • 第 19 行,由于填充了 3 个通道,此时的通道长度变为 3。

阻塞条件

带缓冲通道在很多特性上和无缓冲通道是类似的。无缓冲通道可以看作是长度永远为 0 的带缓冲通道。因此根据这个特性,带缓冲通道在下面列举的情况下依然会发生阻塞:

  • 带缓冲通道被填满时,尝试再次发送数据时发生阻塞。

  • 带缓冲通道为空时,尝试接收数据时发生阻塞。

为什么Go语言对通道要限制长度而不提供无限长度的通道?

我们知道通道(channel)是在两个 goroutine 间通信的桥梁。使用 goroutine 的代码必然有一方提供数据,一方消费数据。当提供数据一方的数据供给速度大于消费方的数据处理速度时,如果通道不限制长度,那么内存将不断膨胀直到应用崩溃。因此,限制通道的长度有利于约束数据提供方的供给速度,供给数据量必须在消费方处理量+通道长度的范围内,才能正常地处理数据。

来源:http://c.biancheng.net/view/100.html

标签:Go语言,缓冲通道
0
投稿

猜你喜欢

  • 在Matplotlib图中插入LaTex公式实例

    2023-09-05 12:23:38
  • MYSQL数据库中cmd命令操作详解

    2024-01-18 16:08:01
  • HTML5 的五个激动人心的特性

    2009-01-02 17:36:00
  • Python栈算法的实现与简单应用示例

    2023-11-16 23:18:30
  • 关于Python中的同步异步阻塞与非阻塞

    2021-09-03 05:54:01
  • 在python中利用dict转json按输入顺序输出内容方式

    2021-10-26 15:17:23
  • js中创建对象的几种方式

    2024-04-10 10:44:41
  • 《色彩解答》系列之三 色彩对比

    2008-02-17 14:40:00
  • 用JS找出字符串中出现次数最多的字母

    2007-11-12 13:40:00
  • Sql Server datetime问题

    2024-01-27 03:06:25
  • python使用urllib2提交http post请求的方法

    2023-11-24 19:35:53
  • 轻松了解数据库计算机的概念和发展方向

    2009-01-23 13:55:00
  • asp封装dll源码分享

    2008-09-25 17:20:00
  • 快速一键生成Python爬虫请求头

    2022-05-21 01:00:53
  • python 图片验证码代码分享

    2022-02-21 17:10:27
  • 仿淘宝星级评分效果

    2010-09-03 18:37:00
  • Python爬虫 批量爬取下载抖音视频代码实例

    2021-08-02 23:25:10
  • 书写高效的CSS - 漫谈CSS的渲染效率

    2008-07-13 14:20:00
  • 一文教会你用Python读取PDF文件

    2021-03-23 00:24:55
  • Python实现爬取天气数据并可视化分析

    2023-02-09 00:33:14
  • asp之家 网络编程 m.aspxhome.com