Go?channel結(jié)構(gòu)體源碼和讀寫和關(guān)閉過(guò)程詳解
- 簡(jiǎn)而言之,channel維護(hù)了一個(gè)帶指針的接受和發(fā)送的隊(duì)列,其中包含mutex鎖保證并發(fā)安全,數(shù)據(jù)類型,元素個(gè)數(shù),元素大小,channel狀態(tài)
- 然后讀寫操作,先看隊(duì)列是否可以取出,然后看緩沖區(qū),最后放入接受/發(fā)送隊(duì)列
- 關(guān)閉就是喚醒所有g(shù)oroutine然后將他們的標(biāo)志位設(shè)為1,表示關(guān)閉,以后有人訪問(wèn)就是nil
結(jié)構(gòu)體源碼
type hchan struct { qcount uint // 當(dāng)前隊(duì)列中元素的數(shù)量 dataqsiz uint // 緩沖區(qū)大小,即可以緩存的元素?cái)?shù)量 buf unsafe.Pointer // 指向隊(duì)列的緩沖區(qū) elemsize uint16 // 每個(gè)元素的大小 closed uint32 // channel 是否已關(guān)閉的標(biāo)志 elemtype *_type // channel 中元素的類型 sendx uint // 下一次發(fā)送元素的位置 recvx uint // 下一次接收元素的位置 recvq waitq // 等待接收的 goroutine 隊(duì)列 sendq waitq // 等待發(fā)送的 goroutine 隊(duì)列 lock mutex // 用于保護(hù) channel 的互斥鎖 }
發(fā)送數(shù)據(jù)
當(dāng)一個(gè) goroutine 要向 channel 中發(fā)送數(shù)據(jù)時(shí),它會(huì)執(zhí)行 chansend
函數(shù)。
- 這個(gè)函數(shù)首先會(huì)對(duì) channel 進(jìn)行加鎖,然后判斷是否有等待接收的 goroutine
- 如果有,則直接將數(shù)據(jù)發(fā)送給它;否則,如果緩沖區(qū)未滿,則將數(shù)據(jù)放入緩沖區(qū),隊(duì)列中元素?cái)?shù)量加一;
- 如果隊(duì)列已滿,則將當(dāng)前 goroutine 加入等待發(fā)送的 goroutine 隊(duì)列中,并阻塞它,等待其他 goroutine 接收數(shù)據(jù)。
接受數(shù)據(jù)
當(dāng)一個(gè) goroutine 要從 channel 中接收數(shù)據(jù)時(shí),它會(huì)執(zhí)行 src/runtime/chan.go
中的 chanrecv
函數(shù)。
- 這個(gè)函數(shù)也會(huì)對(duì) channel 進(jìn)行加鎖,然后判斷是否有等待發(fā)送的 goroutine,如果有,則直接從它那里接收數(shù)據(jù);
- 否則,如果緩沖區(qū)元素的數(shù)量大于 0,則從緩沖區(qū)中取出一個(gè)元素,并將隊(duì)列中元素?cái)?shù)量減一。
- 如果緩沖區(qū)為空,則將當(dāng)前 goroutine 加入等待接收的 goroutine 隊(duì)列中,并阻塞它,等待其他 goroutine 發(fā)送數(shù)據(jù)。
關(guān)閉channel
當(dāng)一個(gè) goroutine 要關(guān)閉 channel 時(shí),它會(huì)執(zhí)行 src/runtime/chan.go
中的 closechan
函數(shù)。
- 這個(gè)函數(shù)會(huì)對(duì) channel 進(jìn)行加鎖,然后將
closed
標(biāo)志置為 1,表示 channel 已經(jīng)關(guān)閉。 - 然后遍歷等待發(fā)送和等待接收的 goroutine 隊(duì)列,將它們?nèi)繂拘?,并返回一個(gè)特殊的值來(lái)表示 channel 已經(jīng)關(guān)閉。
到此這篇關(guān)于Go channel結(jié)構(gòu)體源碼和讀寫和關(guān)閉過(guò)程的文章就介紹到這了,更多相關(guān)go channel結(jié)構(gòu)體源碼內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
golang?chan傳遞數(shù)據(jù)的性能開銷詳解
這篇文章主要為大家詳細(xì)介紹了Golang中chan在接收和發(fā)送數(shù)據(jù)時(shí)因?yàn)椤皬?fù)制”而產(chǎn)生的開銷,文中的示例代碼講解詳細(xì),感興趣的小伙伴可以了解下2024-01-01Go的gin參數(shù)校驗(yàn)中的validator庫(kù)詳解
這篇文章主要介紹了Go的gin參數(shù)校驗(yàn)之validator庫(kù),使用 validator 以后,只需要在定義結(jié)構(gòu)體時(shí)使用 binding 或 validate tag標(biāo)識(shí)相關(guān)校驗(yàn)規(guī)則,就可以進(jìn)行參數(shù)校驗(yàn)了,而不用自己?jiǎn)为?dú)去寫常見的校驗(yàn)規(guī)則,需要的朋友可以參考下2023-08-08Go語(yǔ)言遍歷map實(shí)現(xiàn)(訪問(wèn)map中的每一個(gè)鍵值對(duì))
這篇文章主要介紹了Go語(yǔ)言遍歷map實(shí)現(xiàn)(訪問(wèn)map中的每一個(gè)鍵值對(duì)),文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2021-01-01Go1.18新特性工作區(qū)模糊測(cè)試及泛型的使用詳解
這篇文章主要為大家介紹了Go?1.18新特性中的工作區(qū)?模糊測(cè)試?泛型使用進(jìn)行詳細(xì)講解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-07-07