首頁 > 後端開發 > Golang > 主體

關於Golang channel的實現

藏色散人
發布: 2021-05-06 10:00:17
轉載
2290 人瀏覽過

以下由golang教學專欄跟大家介紹關於Golang channel的實現,希望對需要的朋友有幫助!

一.簡介

       channel是Go語言在語言層級提供的goroutine間的溝通方式,可以使用channel在兩個或多個goroutine之間傳遞訊息。 channel是進程內通訊方式,因此透過channel傳遞物件的過程和呼叫函數時的參數傳遞行為比較一致,例如也可以傳遞指標。如果需要跨進程通信,建議使用分散式系統來解決,例如使用Socket或HTTP等通信協定。

       channel是型別相關的,也就是說,一個chennel只能傳遞一個型別的值,這個型別需要在宣告channel時指定。注意,在GO語言中channel本身也是一個原生類型,與map之類的類型地位一樣,因此channel本身在定義後也可以透過channel傳遞。

二.底層實作

2.1 hchan結構

type hchan struct {
   qcount   uint           // 队列中当前数据的个数
   dataqsiz uint           // size of the circular queue
   buf      unsafe.Pointer // 数据缓冲区,存放数据的环形数组
   elemsize uint16 // channel中数据类型的大小(单个元素的大小)
   closed   uint32 // 表示channel是否关闭标识位
   elemtype *_type // 队列中的元素类型
   sendx    uint   // 当前发送元素的索引
   recvx    uint   // 当前接收元素的索引
   recvq    waitq  // 接受等待队列,由recv行为(也就是<-ch)阻塞在channel上的goroutine队列
   sendq    waitq  // 发送等待队列, 由send行为(也就是ch<-)阻塞在channel上的goroutine队列
   //lock保护chann中的所有字段,以及在此通道上阻塞的sudoG中的几个字段。
   //保持此锁时不要更改另一个G状态(特别是没准备好G),因为这可能会因堆栈收缩而死锁
   lock mutex
}

//发送及接收队列的·1结构体
type waitq struct {
    first *sudog
    last  *sudog
}
登入後複製
  • qcount uint // 目前佇列中剩餘元素個數。
  • dataqsiz uint // 環形佇列長度,即緩衝區的大小,即make(chan T,N),N。
  • buf unsafe.Pointer // 環形佇列指標。
  • elemsize uint16 // 每個元素的大小。
  • closed uint32 // 表示目前頻道是否處於關閉狀態。建立通道後,此欄位設為0,即通道開啟; 透過呼叫close將其設為1,通道關閉。
  • elemtype *_type // 元素類型,用於資料傳遞過程中的賦值。
  • sendx uint 和 recvx uint是環形緩衝區的狀態字段,它指示緩衝區的當前索引- 支援數組,它可以從中發送資料和接收數據。
  • recvq waitq // 等待讀取訊息的goroutine佇列。
  • sendq waitq // 等待寫​​訊息的goroutine隊列。
  • lock mutex // 互斥鎖,為每個讀寫操作鎖定通道,因為傳送和接收必須是互斥操作。

 

2.2 建立流程

2.2.1 寫入動作

1.建立帶有buffer的channel

#2.寫入資料

#3.3 寫入過程如下:

  • 鎖定整個管道結構。
  • 確定寫入,嘗試從等會帶隊列等待goroutine,然後將元素直接寫入goroutine。
  • 如果recvq為空,則確定緩衝區是否可用。如果可用,請從目前goroutine複製資料到緩衝區。
  • 如果緩衝區已滿,則要寫入的元素將保存在目前正在執行的goroutine結構中,並且當前goroutine將在sendq中排隊並從運行中掛起。
  • 寫入完成釋放鎖定。

2.2.2 讀取過程

  • 先讀取channel全域鎖定。
  • 嘗試sendq從等待隊列中取得等待的goroutine。
  • 如果有等待的goroutine,且有緩衝區(緩衝區已滿),從緩衝區隊首取出數據,再從sendq取出一個goroutine。將goroutine中資料存入buf對位,結束讀取釋放鎖。
  • 如沒有後等待的goroutine,且緩衝區有數據,直接讀取緩衝區數據,解釋讀取釋放鎖。
  • 如果沒有等待的goroutine,且沒有緩衝或緩衝區域為空,將當前的goroutine加入denq排隊,進入睡眠,等待被寫goroutine喚醒。結束釋放鎖。
#

以上是關於Golang channel的實現的詳細內容。更多資訊請關注PHP中文網其他相關文章!

相關標籤:
來源:csdn.net
本網站聲明
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn
熱門教學
更多>
最新下載
更多>
網站特效
網站源碼
網站素材
前端模板