go Channel 原理 (一)

Channel

設計原理

不要通過共享內存的方式進行通信,而是應該通過通信的方式共享內存。

在主流編程語言中,多個線程傳遞數據的方式一般都是共享內存
在這里插入圖片描述
Go 可以使用共享內存加互斥鎖進行通信,同時也提供了一種不同的并發模型,即通信順序進程(Communicating sequential processes,CSP)。Goroutine 和 Channel 分別對應 CSP 中的實體和傳遞信息的媒介,Goroutine 之間會通過 Channel 傳遞數據。
在這里插入圖片描述
上圖中的兩個 Goroutine,一個會向 Channel 中發送數據,另一個會從 Channel 中接收數據,它們兩者能夠獨立運行并不存在直接關聯,但是能通過 Channel 間接完成通信。

數據結構

type hchan struct {// 循環隊列// 元素數量 qcount   uint           // total data in the queue// 隊列的長度dataqsiz uint           // size of the circular queue// 緩沖區大小 有緩沖的 channel 才有buf      unsafe.Pointer // points to an array of dataqsiz elements// 已發送和接收元素在隊列中的索引sendx    uint   // send indexrecvx    uint   // receive index// 元素類型和大小elemsize uint16elemtype *_type // element type// channel 是否已關閉closed   uint32// 等待接受和發送的 goroutine 隊列recvq    waitq  // list of recv waiterssendq    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
}

sendqrecvq 存儲了當前 Channel 由于緩沖區空間不足而阻塞的 Goroutine 列表,這些等待隊列使用雙向鏈表 runtime.waitq 表示,鏈表中所有的元素都是 runtime.sudog 結構,runtime.sudog 表示一個在等待列表中的 Goroutine。

type waitq struct {first *sudoglast  *sudog
}

在這里插入圖片描述

創建 channel

通道有兩個方向,發送和接收。
一般而言,使用 make 創建一個能收能發的通道:

// 無緩沖通道
ch1 := make(chan int)
// 有緩沖通道
ch2 := make(chan int, 10)

創建 chan 的函數是 makechan:

func makechan(t *chantype, size int64) *hchan

創建的 chan 是一個指針,所以我們能在函數間直接傳遞 channel,而不用傳遞 channel 的指針。

const hchanSize = unsafe.Sizeof(hchan{}) + uintptr(-int(unsafe.Sizeof(hchan{}))&(maxAlign-1))func makechan(t *chantype, size int64) *hchan {elem := t.elem// 省略了檢查 channel size,align 的代碼// ……var c *hchan// 如果元素類型不含指針 或者 size 大小為 0(無緩沖類型)// 只進行一次內存分配if elem.kind&kindNoPointers != 0 || size == 0 {// 如果 hchan 結構體中不含指針,GC 就不會掃描 chan 中的元素// 只分配 "hchan 結構體大小 + 元素大小*個數" 的內存c = (*hchan)(mallocgc(hchanSize+uintptr(size)*elem.size, nil, true))// 如果是緩沖型 channel 且元素大小不等于 0(大小等于 0的元素類型:struct{})if size > 0 && elem.size != 0 {c.buf = add(unsafe.Pointer(c), hchanSize)} else {// race detector uses this location for synchronization// Also prevents us from pointing beyond the allocation (see issue 9401).// 1. 非緩沖型的,buf 沒用,直接指向 chan 起始地址處// 2. 緩沖型的,能進入到這里,說明元素無指針且元素類型為 struct{},也無影響// 因為只會用到接收和發送游標,不會真正拷貝東西到 c.buf 處(這會覆蓋 chan的內容)c.buf = unsafe.Pointer(c)}} else {// 進行兩次內存分配操作c = new(hchan)c.buf = newarray(elem, int(size))}// 更新字段c.elemsize = uint16(elem.size)c.elemtype = elemc.dataqsiz = uint(size)return c
}

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/web/37129.shtml
繁體地址,請注明出處:http://hk.pswp.cn/web/37129.shtml
英文地址,請注明出處:http://en.pswp.cn/web/37129.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

npm ci vs npm i

npm ci vs npm i 幾個關鍵區別:該選擇哪個? 通過 npm ci 和 npm i 兩個命令,都可安裝項目的依賴。那么這兩個命令有什么區別呢? 幾個關鍵區別: 目的和用途: npm ci :根據項目中的 package-lock…

AI奏響未來樂章:音樂界的革命性變革

AI在創造還是毀掉音樂 引言 隨著科技的飛速發展,人工智能(AI)正在逐漸滲透到我們生活的每一個角落,音樂領域也不例外。AI技術的引入,不僅為音樂創作、教育、體驗帶來了革命性的變革,更為整個音樂產業注入了…

順序表應用——通訊錄

在本篇之前的順序表專題我們已經學習的順序表的實現,了解了如何實現順序表的插入和刪除等功能,那么在本篇當中就要學習基于順序表來實現通訊錄,在通訊錄當中能實現聯系人的增、刪、查改等功能,接下來就讓我們一起來實現通訊錄吧&a…

grpc學習golang版( 五、多proto文件示例 )

系列文章目錄 第一章 grpc基本概念與安裝 第二章 grpc入門示例 第三章 proto文件數據類型 第四章 多服務示例 第五章 多proto文件示例 第六章 服務器流式傳輸 第七章 客戶端流式傳輸 第八章 雙向流示例 文章目錄 一、前言二、定義proto文件2.1 公共proto文件2.2 語音喚醒proto文…

解決Vue3項目中跨域問題的步驟

決Vue3項目中跨域問題的步驟可以按照以下方式清晰地分點表示和歸納: 1. 使用代理服務器(Proxy) 步驟: 在Vue項目的根目錄下找到或創建vue.config.js文件。在vue.config.js中配置devServer的proxy選項。設定需要代理的接口前綴&a…

基于局域網下的服務器連接、文件傳輸以及內網穿透教程 | 服務器連接ssh | 服務器文件傳輸scp | 內網穿透frp | 研究生入學必備 | 深度學習必備

🙋大家好!我是毛毛張! 🌈個人首頁: 神馬都會億點點的毛毛張 📌本篇博客分享的是基于局域網下的服務器連接🔗、文件傳輸以及內網穿透教程,內容非常完備?,涵蓋了在服務器上做深度學…

樹莓派3B讀寫EEPROM芯片AT24C256

AT24C256是一個Atmel公司的EEPROM存儲芯片,容量是256K個bit(也就是32K字節),I2C接口,而樹莓派正好有I2C接口,如下圖藍框中的4個IO口, 把AT24C256和這4個口接在一起,這樣硬件就準備好…

Django 頁面展示模型創建表的數據

1,添加視圖函數 Test/app8/urls.py from django.shortcuts import render from .models import Userdef create_user(request):if request.method POST:username request.POST.get(username)email request.POST.get(email)# ... 獲取其他字段的值# 創建用戶實例…

【Python學習篇】Python實驗小練習——異常處理(十三)

個人名片: 🎓作者簡介:嵌入式領域優質創作者🌐個人主頁:妄北y 📞個人QQ:2061314755 💌個人郵箱:[mailto:2061314755qq.com] 📱個人微信:Vir2025WB…

【教程】5分鐘直接了解隨機森林模型

本文來自《老餅講解-BP神經網絡》https://www.bbbdata.com/ 目錄 一、什么是隨機森林模型1.1.隨機森林模型介紹1.2.為什么隨機森林要用多棵決策樹 二、怎么訓練一個隨機森林模型2.1.訓練一個隨機森林模型 隨機森林模型是機器學習中常用的模型之一,它是決策樹模型的一…

Node.js全棧指南:靜態資源服務器

上一章【認識 MIME 和 HTTP】。 我們認識和了解了 MIME 的概念和作用,也簡單地學習了通過瀏覽器控制臺查看請求和返回的用法。 通過對不同的 HTML、CSS、JS 文件進行判斷,設置不同的 MIME 值,得以讓我們的瀏覽器正正確地接收和顯示不同的文…

八爪魚現金流-031,寬帶到期記一筆負債

到期了,新弄的網絡,記錄一下負債包。 八爪魚現金流 八爪魚

英英詞典(匯編實驗)

功能要求: 1.單詞及其英文解釋的錄入、修改和刪除 (1 ) 錄入新單詞,把它插入到相應的位置(按詞典順序),其后跟英文解釋、同義詞、反義詞;(此功能要求在文件中完成,其它功能可以將單詞放在數據段中&#xf…

數據庫原理之數據庫基本概念

目錄 前言 基本概念 數據庫完整性 前言 今天我們來看看數據庫的基本概念,幫助大家對數據庫有一點點最基本的了解 基本概念 4個基本概念 數據data:描述事物的符號,數據庫中存儲的基本對象。 數據庫Database:長期存儲在計算機…

山東大學多核并行2024年回憶版

2024.6.13回憶版 矩陣向量乘不可整除代碼 集合通信與點對點通信的區別 塊劃分、循環劃分、循環塊劃分(14個向量,4個進程) 按行訪問還是按列訪問快 SISD系統問題 循環依賴問題 問題:為什么不能對這個循環并行化&#xff0…

Python邏輯控制語句 之 綜合案例

需求: 1. 提示?戶輸?登錄系統的?戶名和密碼 2. 校驗?戶名和密碼是否正確(正確的?戶名:admin、密碼:123456) 3. 如果?戶名和密碼都正確,打印“登錄成功!”,并結束程序 4. 如果?戶名或密碼錯誤,打印“?戶名或密碼錯誤!”…

Django 對模型創建的兩表插入數據

1,添加模型 Test/app8/models.py from django.db import modelsclass User(models.Model):username models.CharField(max_length50, uniqueTrue)email models.EmailField(uniqueTrue)password models.CharField(max_length128) # 使用哈希存儲密碼first_name …

代碼隨想錄算法訓練營第一天 [300.最長遞增子序列 674. 最長連續遞增序列 718. 最長重復子數組]

代碼隨想錄算法訓練營第一天 [300.最長遞增子序列 674. 最長連續遞增序列 718. 最長重復子數組] **一、300.最長遞增子序列 ** 鏈接: 代碼隨想錄. 思路:dp[i] 以nums[i]為結尾的遞增子序列最大長度,下標為i的數,需要和下標為0開始一直到下標為…

DM 的斷點續傳測試

作者: 大魚海棠 原文來源: https://tidb.net/blog/4540ae34 一、概述 DM有all、full、incremental三種數據遷移同步方式(task-mode),在all同步模式下,因一些特殊情況,需要變更上游MySQL的數…