Go通道channel通過通信共享內(nèi)存
引言
不要通過共享內(nèi)存來通信 應(yīng)該通過通信來共享內(nèi)存
這句話有網(wǎng)友的解釋如下:
這句俏皮話具體說來就是,不同的線程不共享內(nèi)存不用鎖,線程之間通訊用通道(channel)同步也用channel。
chanel是協(xié)程之間傳遞信息的媒介,優(yōu)雅地解決了某些后端開發(fā)常用語(yǔ)言中隨處可見的lock,unlock,臨界區(qū)等,把從很多線程層面解決的問題移到協(xié)程,從而靜態(tài)地保證沒有數(shù)據(jù)競(jìng)爭(zhēng)。
通道的聲明與創(chuàng)建
偽代碼如下:
//聲明類型 var 通道名 chan 數(shù)據(jù)類型 //創(chuàng)建通道 通道名 = make(chan 數(shù)據(jù)類型)
實(shí)際例子如下:
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) } }
運(yùn)行結(jié)果是:
chan int, <nil>
chan int, 0x1400001a360
通道是一個(gè)內(nèi)存地址,這也說明了其實(shí)一個(gè)引用類型的數(shù)據(jù)。
接收 & 發(fā)送數(shù)據(jù)
對(duì)于同一個(gè)通道來講,他的讀數(shù)據(jù) 和 寫數(shù)據(jù) 都是阻塞的。
偽代碼如下:
//從通道讀數(shù)據(jù) data := <-a //把數(shù)據(jù)寫入通道 a <- data
實(shí)際例子如下:
package main import "fmt" func main() { // 首先創(chuàng)建一個(gè)bool類型的通道 var ch1 chan bool ch1 = make(chan bool) //下面啟動(dòng)一個(gè)go routine go func() { for i := 0; i < 10; i++ { fmt.Println("子goroutine中, i: ", i) } fmt.Println("completed") //循環(huán)結(jié)束后 向團(tuán)隊(duì)中寫數(shù)據(jù),表示要結(jié)束了 ch1 <- true }() //在主程序中讀取數(shù)據(jù) data := <-ch1 //打印一下 我們讀到的數(shù)據(jù) fmt.Println("main data: ", data) fmt.Println("main goroutine completed") }
運(yùn)行結(jié)果如下:
子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里面 循環(huán)打印1~10, 打印完成之后 把chanel類型的ch1寫為true,
這時(shí)候,主goroutine就可以根據(jù)這一條件進(jìn)行下一步了,,在此之前,其實(shí)就算主goroutine先搶到了資源,從ch1中讀取數(shù)據(jù),但是現(xiàn)在通道里面啥都沒有,只能阻塞,然后乖乖交出資源給我們的子goroutine,直到循環(huán)結(jié)束寫true入ch1。
需要注意的有以下幾點(diǎn):
- chanel是需要指定類型的 nil類型的chanel不能直接使用。
- chanel本身是同步的,同一時(shí)間只能有一條goroutine進(jìn)行操作。
- chanel是goroutine之間傳遞數(shù)據(jù)用的,chanel數(shù)據(jù)的發(fā)送和接收必須在不同的goroutine中,如果只有一條goroutine是用不上chanel的,這種情況會(huì)發(fā)生死鎖(deadLock)。
- 從chanel里面讀數(shù)據(jù)立馬就會(huì)被阻塞,直到有向chanel寫數(shù)據(jù)的goroutine來。
- 向chanel里面寫數(shù)據(jù)立馬就會(huì)被阻塞,直到有從chanel讀數(shù)據(jù)的goroutine來。
(以上都是相對(duì)于沒有緩存的通道而言,后面講到的緩存通道在緩沖區(qū)滿的時(shí)候才阻塞,而不是立刻阻塞)
以上就是Go通道channel通過通信共享內(nèi)存的詳細(xì)內(nèi)容,更多關(guān)于Go channel通信共享內(nèi)存的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
- golang?channel多協(xié)程通信常用方法底層原理全面解析
- Golang無(wú)限緩存channel的設(shè)計(jì)與實(shí)現(xiàn)解析
- 通過示例深度理解Go channel range
- Go底層channel實(shí)現(xiàn)原理及示例詳解
- Golang?channel為什么不會(huì)阻塞的原因詳解
- goFrame的隊(duì)列g(shù)queue對(duì)比channel使用詳解
- Go語(yǔ)言CSP并發(fā)模型goroutine及channel底層實(shí)現(xiàn)原理
- Go channel發(fā)送方和接收方如何相互阻塞等待源碼解讀
相關(guān)文章
GoAdminGroup/go-admin的安裝和運(yùn)行的教程詳解
這篇文章主要介紹了GoAdminGroup/go-admin的安裝和運(yùn)行的教程詳解,本文通過實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2020-09-09GO語(yǔ)言的控制語(yǔ)句詳解包括GO語(yǔ)言的指針語(yǔ)法
這篇文章主要介紹了GO語(yǔ)言的控制語(yǔ)句詳解包括GO語(yǔ)言的指針語(yǔ)法,GO語(yǔ)言switch結(jié)構(gòu),GO語(yǔ)言for的4種結(jié)構(gòu)需要的朋友可以參考下2022-12-12Golang 使用接口實(shí)現(xiàn)泛型的方法示例
這篇文章主要介紹了Golang 使用接口實(shí)現(xiàn)泛型的方法示例,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2019-03-03Go語(yǔ)言使用sort包對(duì)任意類型元素的集合進(jìn)行排序的方法
這篇文章主要介紹了Go語(yǔ)言使用sort包對(duì)任意類型元素的集合進(jìn)行排序的方法,實(shí)例分析了sort排序所涉及的方法與相關(guān)的使用技巧,需要的朋友可以參考下2015-02-02Go語(yǔ)言狀態(tài)機(jī)的實(shí)現(xiàn)
本文主要介紹了Go語(yǔ)言狀態(tài)機(jī)的實(shí)現(xiàn),文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2023-03-03