網站首頁 編程語言 正文
引言
不要通過共享內存來通信 應該通過通信來共享內存
這句話有網友的解釋如下:
這句俏皮話具體說來就是,不同的線程不共享內存不用鎖,線程之間通訊用通道(channel)同步也用channel。
chanel是協程之間傳遞信息的媒介,優雅地解決了某些后端開發常用語言中隨處可見的lock,unlock,臨界區等,把從很多線程層面解決的問題移到協程,從而靜態地保證沒有數據競爭。
通道的聲明與創建
偽代碼如下:
//聲明類型 var 通道名 chan 數據類型 //創建通道 通道名 = make(chan 數據類型)
實際例子如下:
package main import "fmt" func main() { var a chan int fmt.Printf("%T, %v\n", a, a) if a == nil { a = make(chan int) fmt.Printf("%T, %v\n", a, a) } }
運行結果是:
chan int, <nil>
chan int, 0x1400001a360
通道是一個內存地址,這也說明了其實一個引用類型的數據。
接收 & 發送數據
對于同一個通道來講,他的讀數據 和 寫數據 都是阻塞的。
偽代碼如下:
//從通道讀數據 data := <-a //把數據寫入通道 a <- data
實際例子如下:
package main import "fmt" func main() { // 首先創建一個bool類型的通道 var ch1 chan bool ch1 = make(chan bool) //下面啟動一個go routine go func() { for i := 0; i < 10; i++ { fmt.Println("子goroutine中, i: ", i) } fmt.Println("completed") //循環結束后 向團隊中寫數據,表示要結束了 ch1 <- true }() //在主程序中讀取數據 data := <-ch1 //打印一下 我們讀到的數據 fmt.Println("main data: ", data) fmt.Println("main goroutine completed") }
運行結果如下:
子goroutine中, i: 0
子goroutine中, i: 1
子goroutine中, i: 2
子goroutine中, i: 3
子goroutine中, i: 4
子goroutine中, i: 5
子goroutine中, i: 6
子goroutine中, i: 7
子goroutine中, i: 8
子goroutine中, i: 9
completed
main data: true
main goroutine completed
我們的子goroutine里面 循環打印1~10, 打印完成之后 把chanel類型的ch1寫為true,
這時候,主goroutine就可以根據這一條件進行下一步了,,在此之前,其實就算主goroutine先搶到了資源,從ch1中讀取數據,但是現在通道里面啥都沒有,只能阻塞,然后乖乖交出資源給我們的子goroutine,直到循環結束寫true入ch1。
需要注意的有以下幾點:
- chanel是需要指定類型的 nil類型的chanel不能直接使用。
- chanel本身是同步的,同一時間只能有一條goroutine進行操作。
- chanel是goroutine之間傳遞數據用的,chanel數據的發送和接收必須在不同的goroutine中,如果只有一條goroutine是用不上chanel的,這種情況會發生死鎖(deadLock)。
- 從chanel里面讀數據立馬就會被阻塞,直到有向chanel寫數據的goroutine來。
- 向chanel里面寫數據立馬就會被阻塞,直到有從chanel讀數據的goroutine來。
(以上都是相對于沒有緩存的通道而言,后面講到的緩存通道在緩沖區滿的時候才阻塞,而不是立刻阻塞)
原文鏈接:https://segmentfault.com/a/1190000041888050
相關推薦
- 2022-09-24 C#使用反射機制實現延遲綁定_C#教程
- 2023-02-01 C語言中聯合體與共用體和枚舉使用語法示例_C 語言
- 2023-01-26 Python+Sklearn實現異常檢測_python
- 2022-04-17 Mac使用pandoc 將docx文件轉換成html文件 快速實現協議文件的轉換
- 2022-09-01 Nginx?部署的虛擬主機使用?Let's?Encrypt?加密?https的方法_nginx
- 2021-12-15 幾個小技巧幫你實現Golang永久阻塞_Golang
- 2022-08-20 docker鏡像alpine中安裝oracle客戶端_docker
- 2021-11-12 圖文詳解Flutter單例的實現_Android
- 最近更新
-
- window11 系統安裝 yarn
- 超詳細win安裝深度學習環境2025年最新版(
- Linux 中運行的top命令 怎么退出?
- MySQL 中decimal 的用法? 存儲小
- get 、set 、toString 方法的使
- @Resource和 @Autowired注解
- Java基礎操作-- 運算符,流程控制 Flo
- 1. Int 和Integer 的區別,Jav
- spring @retryable不生效的一種
- Spring Security之認證信息的處理
- Spring Security之認證過濾器
- Spring Security概述快速入門
- Spring Security之配置體系
- 【SpringBoot】SpringCache
- Spring Security之基于方法配置權
- redisson分布式鎖中waittime的設
- maven:解決release錯誤:Artif
- restTemplate使用總結
- Spring Security之安全異常處理
- MybatisPlus優雅實現加密?
- Spring ioc容器與Bean的生命周期。
- 【探索SpringCloud】服務發現-Nac
- Spring Security之基于HttpR
- Redis 底層數據結構-簡單動態字符串(SD
- arthas操作spring被代理目標對象命令
- Spring中的單例模式應用詳解
- 聊聊消息隊列,發送消息的4種方式
- bootspring第三方資源配置管理
- GIT同步修改后的遠程分支