[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