[go] チャネル構造のソース コードと読み取り、書き込み、終了のプロセス

  • つまり、チャネルはポインターを使用して受信キューと送信キューを維持します。このキューには、同時実行セキュリティ、データ型、要素の数、要素のサイズ、およびチャネルのステータスを確保するためのミューテックス ロックが含まれています。
  • 次に、読み取りと書き込みの操作を行い、最初にキューが取り出せるかどうかを確認し、次にバッファを確認し、最後に受信/送信キューに入れます。
  • 閉じるとは、すべてのゴルーチンを起動してフラグを 1 に設定することです。これはゴルーチンが閉じられていることを意味し、将来誰かがそれらを訪問した場合、それらは nil になります。

構造ソースコード

type hchan struct {
    
    
    qcount   uint           // 当前队列中元素的数量
    dataqsiz uint           // 缓冲区大小,即可以缓存的元素数量
    buf      unsafe.Pointer // 指向队列的缓冲区
    elemsize uint16         // 每个元素的大小
    closed   uint32         // channel 是否已关闭的标志
    elemtype *_type         // channel 中元素的类型
    sendx    uint           // 下一次发送元素的位置
    recvx    uint           // 下一次接收元素的位置
    recvq    waitq          // 等待接收的 goroutine 队列
    sendq    waitq          // 等待发送的 goroutine 队列
    lock     mutex          // 用于保护 channel 的互斥锁
}

データを送る

goroutine がチャネルにデータを送信したい場合、 chansend 関数を実行します。

  1. この関数はまずチャネルをロックし、次に受信を待機しているゴルーチンがあるかどうかを判断します。
  2. がある場合は、そこにデータを直接送信します。そうでない場合、バッファがいっぱいでない場合は、データをバッファに入れて、キュー内の要素の数に 1 を加えます。
  3. キューがいっぱいの場合は、現在の goroutine を送信を待機している goroutine のキューに追加し、ブロックして、他の goroutine がデータを受信するのを待ちます。

データを受け入れる

goroutine がチャネルからデータを受信したい場合、 src/runtime/chan.go の 関数を実行しますchanrecv 。

  1. この関数は、チャネルもロックし、送信を待っているゴルーチンがあるかどうかを判断し、存在する場合はそこから直接データを受信します。
  2. それ以外の場合、バッファー要素の数が 0 より大きい場合は、バッファーから要素が取得され、キュー内の要素の数が 1 つ減らされます。
  3. バッファが空の場合は、現在のgoroutine を受信を待機している goroutine のキューに追加し、ブロックして、他の goroutine がデータを送信するのを待ちます。

チャンネルを閉じる

goroutine がチャネルを閉じたい場合、 の src/runtime/chan.go 関数 を実行しますclosechan 。

  1. この関数はチャネルをロックし、 closed チャネルが閉じられていることを示すフラグを 1 に設定します。
  2. 次に、送信と受信を待機しているゴルーチンのキューを走査し、それらをウェイクアップして、チャネルが閉じられていることを示す特別な値を返します。

おすすめ

転載: blog.csdn.net/csxylrf/article/details/130419871
おすすめ