網站首頁 編程語言 正文
引言
上一部分主要寫了鎖,本篇主要介紹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
相關推薦
- 2022-07-02 react用axios的 get/post請求/獲取數據
- 2022-05-23 iOS?Segment帶滑動條切換效果_IOS
- 2024-03-18 SpringBoot + Mybatis 多數據源配置打印SQL失效問題(mybatis.confi
- 2023-07-24 uniapp開發小程序,包過大解決方案
- 2022-07-15 Python中列表索引?A[?:?2?]與A[?:?,?2]的區別說明_python
- 2022-04-23 C語言字符函數isalnum()和iscntrl()詳解_C 語言
- 2022-04-20 Android實現環信修改頭像和昵稱_Android
- 2022-10-11 React - 當輸入框獲取焦點時自動選中輸入框中的內容
- 最近更新
-
- 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同步修改后的遠程分支