日本免费高清视频-国产福利视频导航-黄色在线播放国产-天天操天天操天天操天天操|www.shdianci.com

學無先后,達者為師

網站首頁 編程語言 正文

Go保證并發安全底層實現詳解_Golang

作者:Sundar84034 ? 更新時間: 2022-10-28 編程語言

引言

上一部分主要寫了鎖,本篇主要介紹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的所有行為,基本都是圍繞bufferwaitq來實現的

waitq

type waitq struct { 
 first *sudog 
 last *sudog 
 } 

waitq是一個雙向鏈表,里面保存了goroutine。

buffe

buffer使用 ring buffer(環形緩沖區)實現

在hchan中,可以看到?recvxsendx?兩個屬性,recvx即當前已發送的元素在隊列當中的索引位置,sendx?即 當前已接收的元素在隊列當中的索引位置。

從?recvx?到?sendx?之間的元素,表示已正常存放入 buffer 中的數據。

Lock

hchan中的lock就是一個互斥鎖,channel在發送和接收數據前,都會先進行加鎖,待邏輯完成后執行再解鎖,來保證并發安全。

原文鏈接:https://juejin.cn/post/7026230343581564959

欄目分類
最近更新