網站首頁 編程語言 正文
引言
上一部分主要寫了鎖,本篇主要介紹Channel
channel是Go中非常重要的一個數據類型,它和goroutine緊密相連,是Go的CSP并發模型的重要體現。
CSP
- CSP 是通信順序進程(Communicating Sequential Process)的簡稱,是一種并發編程模型。
- 簡單來說,CSP模型由并發的實體所組成,實體之間通過發送消息進行通信,而發送消息使用的就是通道,即channel。
- GO實現了CSP部分理論,goroutine對應CSP中的并發執行的實體,channel對應CSP中的channel。
不要通過共享內存來通信,而應該通過通信來共享內存
Channel的基本使用
package main import "fmt" func main() { c := make(chan int) go func() { c <- 1 // 向channel發送數據 }() x := <-c // 從channel中接收數據 fmt.Println(x) }
1、通過make(chan int)
創建一個int channel(可以在channel初始化時指定緩沖區的大小,例如make(chan int,2)
,不指定則默認為0)
2、在一個goroutine中,通過c<-1
將數據發送到channel中,<-
可以理解為數據的流動方向。
3、在主goroutine中通過x := <-c
接收channel中的數據,并賦值給x。
channel如何保證并發安全
既然goroutin和channel分別對應csp中的實體和媒介,goroutin之間都是通過chennel來傳遞數據,那么是如何保證并發安全的呢?
通過閱讀源碼可以發現,channel內部是使用Mutext互斥鎖來保證的( 之前也有人提出CAS無鎖Channel的實現,但因為無鎖Channel在多核測試中的表現和沒有滿足FIFO的特性等原因,該提案目前是擱淺狀態)關于無鎖channel的討論
channel的底層實現
channel的核心源碼位于runtime包的chan.go中。
hchan 是 channel 在 golang 中的內部實現
type hchan struct { qcount uint // total data in the queue dataqsiz uint // size of the circular queue buf unsafe.Pointer // points to an array of dataqsiz elements elemsize uint16 closed uint32 elemtype *_type // element type sendx uint // send index recvx uint // receive index recvq waitq // list of recv waiters sendq waitq // list of send waiters // lock protects all fields in hchan, as well as several // fields in sudogs blocked on this channel. // // Do not change another G's status while holding this lock // (in particular, do not ready a G), as this can deadlock // with stack shrinking. lock mutex }
hchan的所有屬性大體可以分為3類
1、buffer相關屬性,當channel中的緩沖區大小不為0時,buffer中存放了待接收的數據。
2、waitq相關屬性,即recvq和sendq,可以理解為一個標準的FIFO隊列,recvq是等待接收數據的goroutine,sendq是等待發送數據的goroutine。
3、其它,例如lock(互斥鎖)、elemtype(元素類型)、closed(channel 是否關閉,== 0 代表未 closed)
hchan的所有行為,基本都是圍繞buffer和waitq來實現的
waitq
type waitq struct { first *sudog last *sudog }
waitq是一個雙向鏈表,里面保存了goroutine。
buffe
buffer使用 ring buffer(環形緩沖區)實現
在hchan中,可以看到?recvx
和sendx
?兩個屬性,recvx
即當前已發送的元素在隊列當中的索引位置,sendx
?即 當前已接收的元素在隊列當中的索引位置。
從?recvx
?到?sendx
?之間的元素,表示已正常存放入 buffer 中的數據。
Lock
hchan中的lock
就是一個互斥鎖,channel在發送和接收數據前,都會先進行加鎖,待邏輯完成后執行再解鎖,來保證并發安全。
原文鏈接:https://juejin.cn/post/7026230343581564959
相關推薦
- 2023-04-02 深入分析Golang?Server源碼實現過程_Golang
- 2022-04-09 C#8.0中的索引與范圍功能介紹_C#教程
- 2022-07-11 使用?Loki?實現?Kubernetes?容器日志監控的方法_相關技巧
- 2022-08-21 caffe的python接口deploy生成caffemodel分類新的圖片_python
- 2022-06-22 SQL實現篩選出連續3天登錄用戶與窗口函數的示例代碼_MsSql
- 2022-08-21 Android設置重復文字水印背景的方法_Android
- 2022-08-13 oracle利用sql語句實現分組小計(grouping,group by ,rollup)
- 2022-10-27 Kotlin?Flow封裝類SharedFlow?StateFlow?LiveData使用對比_An
- 最近更新
-
- window11 系統安裝 yarn
- 超詳細win安裝深度學習環境2025年最新版(
- Linux 中運行的top命令 怎么退出?
- MySQL 中decimal 的用法? 存儲小
- get 、set 、toString 方法的使
- @Resource和 @Autowired注解
- Java基礎操作-- 運算符,流程控制 Flo
- 1. Int 和Integer 的區別,Jav
- spring @retryable不生效的一種
- Spring Security之認證信息的處理
- Spring Security之認證過濾器
- Spring Security概述快速入門
- Spring Security之配置體系
- 【SpringBoot】SpringCache
- Spring Security之基于方法配置權
- redisson分布式鎖中waittime的設
- maven:解決release錯誤:Artif
- restTemplate使用總結
- Spring Security之安全異常處理
- MybatisPlus優雅實現加密?
- Spring ioc容器與Bean的生命周期。
- 【探索SpringCloud】服務發現-Nac
- Spring Security之基于HttpR
- Redis 底層數據結構-簡單動態字符串(SD
- arthas操作spring被代理目標對象命令
- Spring中的單例模式應用詳解
- 聊聊消息隊列,發送消息的4種方式
- bootspring第三方資源配置管理
- GIT同步修改后的遠程分支