[TOC]
### **channel 是否线程安全?锁用在什么地方?**
是线程安全的,channel的底层是一个hchan结构,里面加了mutex
~~~
type hchan struct {
......
lock mutex //互斥锁,chan不允许并发读写
}
~~~
### **go channel 的底层实现原理**
~~~
type hchan struct {
qcount uint
dataqsiz uint
buf unsafe.Pointer
elemsize uint16
closed uint32
elemtype *_type
sendx uint
recvx uint
recvq waitq
sendq waitq
lock mutex //互斥锁,chan不允许并发读写
}
~~~
qcount:channel里面的元素计数。内建函数 len 可以返回这个字段的值。已接收还没被取走
dataqsiz:环形队列大小,即可存放元素的个数。make(chan int,10),10就是这个值
buf:当 channel 设置了缓冲数量时,该 buf 指向一个存储缓冲数据的区域,该区域是一个循环队列的数据结构
elemsize :要发送或接收的数据类型大小
closed :标识关闭状态
elemtype :元素类型
sendx :当 channel 设置了缓冲数量时,数据区域即循环队列此时已发送数据的索引位置
recvx:当 channel 设置了缓冲数量时,数据区域即循环队列此时已接收数据的索引位置
recvq :想读取数据但又被阻塞住的 goroutine 队列,即:等待读消息的goroutine队列
sendq :想发送数据但又被阻塞住的 goroutine 队列,即:等待写消息的goroutine队列
### **channel的特点**
2种类型:有缓冲、无缓冲
3种模式:双向通道,只允许发送通道、只允许接收通道
3种状态:未初始化(nil)、关闭、正常
| | nil | 关闭 | 正常 |
| --- | --- | --- | --- |
| 关闭 | panic | panic | 可以关闭 |
| 发送 | 阻塞导致死锁 | panic | 成功发送/阻塞 |
| 接收 | 阻塞导致死锁 | 缓冲区有值,读值,没有值,返回零值 | 成功接收/阻塞 |
### **向 channel 发送数据和从 channel 读数据的流程是什么样的?**
**向 channel 写数据:**
若等待接收队列 recvq 不为空,无论缓冲区中无数据或无缓冲区,将直接从 recvq 取出 G ,并把数据写入,最后把该 G 唤醒,结束发送过程。
若缓冲区中有空余位置,则将数据写入缓冲区,结束发送过程。
若缓冲区中没有空余位置,则将发送数据写入 G,将当前 G 加入 sendq ,进入睡眠,等待被读 goroutine 唤醒。
**从 channel 读数据**
若等待发送队列 sendq 不为空,且没有缓冲区,直接从 sendq 中取出 G ,把 G 中数据读出,最后把 G 唤醒,结束读取过程。
如果等待发送队列 sendq 不为空,缓冲区已满,从缓冲区中首部读出数据,把 G 中数据写入缓冲区尾部,把 G 唤醒,结束读取过程。
如果缓冲区中有数据,则从缓冲区取出数据,结束读取过程。
如果缓冲区中没有数据,将当前 goroutine 加入 recvq ,进入睡眠,等待被写 goroutine 唤醒。
**关闭 channel**
1.关闭 channel 时会将 recvq 中的 G 全部唤醒,本该写入 G 的数据位置为 nil。将 sendq 中的 G 全部唤醒,但是这些 G 会 panic。
### **chan 使用场景**
消息传递、请求、响应转发,任务分发,限流,同步与异步
- Go准备工作
- 依赖管理
- Go基础
- 1、变量和常量
- 2、基本数据类型
- 3、运算符
- 4、流程控制
- 5、数组
- 数组声明和初始化
- 遍历
- 数组是值类型
- 6、切片
- 定义
- slice其他内容
- 7、map
- 8、函数
- 函数基础
- 函数进阶
- 9、指针
- 10、结构体
- 类型别名和自定义类型
- 结构体
- 11、接口
- 12、反射
- 13、并发
- 14、网络编程
- 15、单元测试
- Go常用库/包
- Context
- time
- strings/strconv
- file
- http
- Go常用第三方包
- Go优化
- Go问题排查
- Go框架
- 基础知识点的思考
- 面试题
- 八股文
- 操作系统
- 整理一份资料
- interface
- array
- slice
- map
- MUTEX
- RWMUTEX
- Channel
- waitGroup
- context
- reflect
- gc
- GMP和CSP
- Select
- Docker
- 基本命令
- dockerfile
- docker-compose
- rpc和grpc
- consul和etcd
- ETCD
- consul
- gin
- 一些小点
- 树
- K8s
- ES
- pprof
- mycat
- nginx
- 整理后的面试题
- 基础
- Map
- Chan
- GC
- GMP
- 并发
- 内存
- 算法
- docker