不做大哥好多年 不做大哥好多年
首页
  • MySQL
  • Redis
  • Elasticsearch
  • Kafka
  • Etcd
  • MongoDB
  • TiDB
  • RabbitMQ
  • 01.GO基础
  • 02.面向对象
  • 03.并发编程
  • 04.常用库
  • 05.数据库操作
  • 06.Beego框架
  • 07.Beego商城
  • 08.GIN框架
  • 09.GIN论坛
  • 10.微服务
  • 01.Python基础
  • 02.Python模块
  • 03.Django
  • 04.Flask
  • 05.SYL
  • 06.Celery
  • 10.微服务
  • 01.Java基础
  • 02.面向对象
  • 03.Java进阶
  • 04.Web基础
  • 05.Spring框架
  • 100.微服务
  • Docker
  • K8S
  • 容器原理
  • Istio
  • 数据结构
  • 算法基础
  • 算法题分类
  • 前置知识
  • PyTorch
  • 01.Python
  • 02.GO
  • 03.Java
  • 04.业务问题
  • 05.关键技术
  • 06.项目常识
  • 10.计算机基础
  • Linux基础
  • Linux高级
  • Nginx
  • KeepAlive
  • ansible
  • zabbix
  • Shell
  • Linux内核

逍遥子

不做大哥好多年
首页
  • MySQL
  • Redis
  • Elasticsearch
  • Kafka
  • Etcd
  • MongoDB
  • TiDB
  • RabbitMQ
  • 01.GO基础
  • 02.面向对象
  • 03.并发编程
  • 04.常用库
  • 05.数据库操作
  • 06.Beego框架
  • 07.Beego商城
  • 08.GIN框架
  • 09.GIN论坛
  • 10.微服务
  • 01.Python基础
  • 02.Python模块
  • 03.Django
  • 04.Flask
  • 05.SYL
  • 06.Celery
  • 10.微服务
  • 01.Java基础
  • 02.面向对象
  • 03.Java进阶
  • 04.Web基础
  • 05.Spring框架
  • 100.微服务
  • Docker
  • K8S
  • 容器原理
  • Istio
  • 数据结构
  • 算法基础
  • 算法题分类
  • 前置知识
  • PyTorch
  • 01.Python
  • 02.GO
  • 03.Java
  • 04.业务问题
  • 05.关键技术
  • 06.项目常识
  • 10.计算机基础
  • Linux基础
  • Linux高级
  • Nginx
  • KeepAlive
  • ansible
  • zabbix
  • Shell
  • Linux内核
  • Python

  • GO

    • 01.GMP模型 ✅
    • 02.Map原理 ✅
    • 03.sync_map ✅
    • 04.sync.Pool
    • 05.垃圾回收 ✅
    • 06.channel
      • 01.channel的整体结构图
        • 1、channel结构图
        • 2、创建channel
        • 3、channel中队列如何实现
        • 4、channel缓存满发生什么
      • 02.chan读写问题
        • 1、对关闭chan读写
        • 2、未初始化chan读写
    • 07.内存逃逸
    • 08.内存泄漏
    • 09.mutex锁原理
    • 10.Go常识
    • 50.Golang常犯错误
    • 51.常见坑1~10
  • Java

  • 业务问题

  • 关键技术

  • 项目常识

  • 计算机基础

  • 常识
  • GO
xiaonaiqiang
2021-06-02
目录

06.channel

# 01.channel的整体结构图

# 1、channel结构图

  • channel本质是一个hchan这个结构体
type hchan struct {
    qcount   uint      // 队列中的元素个数
    dataqsiz uint      // 环形队列的大小,0 表示无缓冲通道
    buf      unsafe.Pointer // 环形队列的指针,用于存储元素
    elemsize uint16    // 单个元素的大小
    closed   uint32    // 表示通道是否关闭,1 表示关闭
    sendx    uint      // 发送操作的下标(对于缓冲通道)
    recvx    uint      // 接收操作的下标(对于缓冲通道)
    recvq    waitq     // 等待接收的 goroutine 队列
    sendq    waitq     // 等待发送的 goroutine 队列
    lock     mutex     // 互斥锁,保证并发安全
    ...
}
1
2
3
4
5
6
7
8
9
10
11
12
13
  • 简单说明:
    • buf 是缓冲区,所有数据存储在这个环形缓冲区中(环形队列)
    • sendx 和 recvx 是指向缓冲区中发送和接收数据位置的指针(管理读写顺序)
      • sendx指针:指向下一个可以写入数据的位置
      • recvx指针:指向下一个可以读取数据的位置
    • recvq 和 sendq 是两个用于存储阻塞 goroutine 的队列(不是用于存储数据的队列)
      • 当缓冲区已满时,无法继续发送,发送 goroutine 会进入 sendq 等待
      • 当缓冲区为空时,无法接收数据,接收 goroutine 会进入 recvq 等待
      • dataqsiz:通道缓冲区的大小,值为 0 表示无缓冲通道
    • lock是个互斥锁,发送或接收前都需要加锁

  • 先进先出
    • 先从 Channel 读取数据的 Goroutine 会先接收到数据
    • 先向 Channel 发送数据的 Goroutine 会得到先发送数据的权利

# 2、创建channel

  • 创建channel实际上就是在内存中实例化了一个hchan的结构体,并返回一个ch指针
  • 我们使用过程中channel在函数之间的传递都是用的这个指针
  • 这就是为什么函数传递中无需使用channel的指针,而直接用channel就行了,因为channel本身就是一个指针

# 3、channel中队列如何实现

  • channel中有个缓存buf,是用来缓存数据的(假如实例化了带缓存的channel的话)队列。

  • 当使用send (ch <- xx)或者recv ( <-ch)的时候,首先要锁住hchan这个结构体

  • 然后开始send (ch <- xx)数据,这时候满了,队列塞不进去了

  • 然后是取recv ( <-ch)的过程,是个逆向的操作,也是需要加锁

# 4、channel缓存满发生什么

  • 使用的时候,我们都知道,当channel缓存满了,或者没有缓存的时候

  • 我们继续send(ch <- xxx)或者recv(<- ch)会阻塞当前goroutine,但是,是如何实现的呢?

  • Go的goroutine是用户态的线程(user-space threads),用户态的线程是需要自己去调度的

  • Go有运行时的scheduler去帮我们完成调度这件事情

# 02.chan读写问题

# 1、对关闭chan读写

  • 读关闭chan
    • 可以正确读取到,如果无元素,返回零值,第二个 bool 值一直为 false
  • 写关闭chan:chan 会 panic

# 2、未初始化chan读写

  • 读取未初始化的通道(nil chan)
    • 程序将永远阻塞在这个读取操作上,因为 nil 通道没有能力传输数据
var ch chan int
x := <-ch // 试图从未初始化的通道读取
1
2
  • 写入未初始化的通道(nil chan)

    • 程序同样会永远阻塞在这个写入操作
  • select 语句中操作未初始化的通道

var ch chan int
select {
    case x := <-ch:
        // 永远不会执行
    case ch <- 1:
        // 永远不会执行
    default:
        // 如果有 default 分支,它会被执行
}
1
2
3
4
5
6
7
8
9
上次更新: 2025/2/25 11:09:45
05.垃圾回收 ✅
07.内存逃逸

← 05.垃圾回收 ✅ 07.内存逃逸→

最近更新
01
04.数组双指针排序_子数组
03-25
02
08.动态规划
03-25
03
06.回溯算法
03-25
更多文章>
Theme by Vdoing | Copyright © 2019-2025 逍遥子 技术博客 京ICP备2021005373号
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式