Go 語(yǔ)言中如何理解協(xié)程通信實(shí)現(xiàn)的消息傳遞篇,針對(duì)這個(gè)問題,這篇文章詳細(xì)介紹了相對(duì)應(yīng)的分析和解答,希望可以幫助更多想解決這個(gè)問題的小伙伴找到更簡(jiǎn)單易行的方法。
創(chuàng)新互聯(lián)公司是一家專注于成都網(wǎng)站設(shè)計(jì)、網(wǎng)站制作與策劃設(shè)計(jì),渦陽(yáng)網(wǎng)站建設(shè)哪家好?創(chuàng)新互聯(lián)公司做網(wǎng)站,專注于網(wǎng)站建設(shè)十多年,網(wǎng)設(shè)計(jì)領(lǐng)域的專業(yè)建站公司;建站業(yè)務(wù)涵蓋:渦陽(yáng)等地區(qū)。渦陽(yáng)做網(wǎng)站價(jià)格咨詢:18980820575
通過共享內(nèi)存實(shí)現(xiàn)協(xié)程通信,這種方式太過繁瑣,且維護(hù)成本高,Go 語(yǔ)言推薦使用消息傳遞實(shí)現(xiàn)并發(fā)通信,這種消息通信機(jī)制被稱為 channel
,中文譯作「通道」,可理解為傳遞消息的通道。
通道是 Go 語(yǔ)言在語(yǔ)言級(jí)別提供的協(xié)程通信方式,它是一種數(shù)據(jù)類型,本身是并發(fā)安全的,我們可以使用它在多個(gè) goroutine 之間傳遞消息,而不必?fù)?dān)心通道中的數(shù)據(jù)被污染。
注:需要注意的是,通道是進(jìn)程內(nèi)的通信方式,因此通過通道傳遞對(duì)象的過程和調(diào)用函數(shù)時(shí)的參數(shù)傳遞行為比較一致,也可以傳遞指針。如果需要跨進(jìn)程通信,建議通過分布式系統(tǒng)的方法來解決,比如使用 Socket 或者 HTTP 等通信協(xié)議,Go 語(yǔ)言對(duì)于網(wǎng)絡(luò)方面也有非常完善的支持,學(xué)院君會(huì)在介紹完并發(fā)編程后介紹網(wǎng)絡(luò)通信。
前面我們說到通道是一種數(shù)據(jù)類型,和數(shù)組類型類似,一個(gè)通道只能傳遞一種類型的值,這個(gè)類型需要在聲明通道時(shí)指定。在使用通道時(shí),需要通過 make
進(jìn)行聲明,通道對(duì)應(yīng)的類型關(guān)鍵字是 chann
:
ch := make(chan int)
這里我們初始化了一個(gè)通道類型 ch
,其中只能傳遞 int
類型的值。
我們可以把通道看作是一個(gè)先進(jìn)先出(FIFO)的隊(duì)列,通道中的元素會(huì)嚴(yán)格按照發(fā)送順序排列,繼而按照排列順序被接收,通道元素的發(fā)送和接收都可以通過 <-
操作符來實(shí)現(xiàn),發(fā)送時(shí)元素值在右,通道變量在左:
ch <- 1 // 表示把元素 1 發(fā)送到通道 ch
接收時(shí)通道變量在右,可以通過指定變量接收元素值:
element := <-ch
也可以留空表示忽略:
<-ch
這樣一來,通過箭頭指向我們就可以清楚的判斷是寫入數(shù)據(jù)到通道還是從通道讀取數(shù)據(jù),非常簡(jiǎn)單形象。
在系統(tǒng)介紹通道類型的完整語(yǔ)法前,我們先看通過通道類型重寫上篇教程通過共享內(nèi)存實(shí)現(xiàn)協(xié)程通信的代碼,創(chuàng)建一個(gè) channel.go
文件,編寫代碼如下:
package main
import (
"fmt"
"time"
)
func add(a, b int, ch chan int) {
c := a + b
fmt.Printf("%d + %d = %d\n", a, b, c)
ch <- 1
}
func main() {
start := time.Now()
chs := make([]chan int, 10)
for i := 0; i < 10; i++ {
chs[i] = make(chan int)
go add(1, i, chs[i])
}
for _, ch := range chs {
<- ch
}
end := time.Now()
consume := end.Sub(start).Seconds()
fmt.Println("程序執(zhí)行耗時(shí)(s):", consume)
}
在這個(gè)例子中,我們首先定義了一個(gè)包含 10 個(gè)通道類型的數(shù)組 chs
,并把數(shù)組中的每個(gè)通道分配給 10 個(gè)不同的協(xié)程。在每個(gè)協(xié)程的 add()
函數(shù)業(yè)務(wù)邏輯完成后,我們通過 ch <- 1
語(yǔ)句向?qū)?yīng)的通道中發(fā)送一個(gè)數(shù)據(jù)。在所有的協(xié)程啟動(dòng)完成后,我們?cè)偻ㄟ^ <-ch
語(yǔ)句從通道數(shù)組 chs
中依次接收數(shù)據(jù)(不對(duì)結(jié)果做任何處理,相當(dāng)于寫入通道的數(shù)據(jù)只是個(gè)標(biāo)識(shí)而已,表示這個(gè)通道所屬的協(xié)程邏輯執(zhí)行完畢),直到所有通道數(shù)據(jù)接收完畢,然后打印主程序耗時(shí)并退出。
之所以上述這段代碼可以實(shí)現(xiàn)和「共享內(nèi)存+鎖」一樣的效果,是因?yàn)橥ǖ缹懭霐?shù)據(jù)和從通道接收數(shù)據(jù)都是原子操作,或者說是同步阻塞的,當(dāng)我們向某個(gè)通道寫入數(shù)據(jù)時(shí),就相當(dāng)于該通道被加鎖,直到寫入操作完成才能執(zhí)行從該通道讀取數(shù)據(jù)的操作,反過來,當(dāng)我們從某個(gè)通道讀取數(shù)據(jù)時(shí),其他協(xié)程也不能操作該通道,直到讀取完成,如果通道中沒有數(shù)據(jù),則會(huì)阻塞在這里,直到通道被寫入數(shù)據(jù)。因此,可以看到通道的發(fā)送和接收操作是互斥的,同一時(shí)間同一個(gè)進(jìn)程內(nèi)的所有協(xié)程對(duì)某個(gè)通道只能執(zhí)行發(fā)送或接收操作,兩者不可能同時(shí)進(jìn)行,這樣就保證了并發(fā)的安全性,數(shù)據(jù)不可能被污染。
綜上可知,上述示例代碼 main()
函數(shù)中的第二個(gè)循環(huán)會(huì)等到所有子協(xié)程執(zhí)行完畢后才能完成所有通道的接收操作。我們可以執(zhí)行下這段代碼,輸出結(jié)果如下:
程序耗時(shí)和共享內(nèi)存相當(dāng),但是代碼要簡(jiǎn)潔的多,優(yōu)雅的多。當(dāng)然,本篇教程只是介紹了通道的最基本使用,接下來,我將花幾個(gè)教程的篇幅為大家系統(tǒng)介紹通道,并結(jié)合協(xié)程(goroutine)+通道(channel)為大家展現(xiàn) Go 并發(fā)編程的魅力。
關(guān)于Go 語(yǔ)言中如何理解協(xié)程通信實(shí)現(xiàn)的消息傳遞篇問題的解答就分享到這里了,希望以上內(nèi)容可以對(duì)大家有一定的幫助,如果你還有很多疑惑沒有解開,可以關(guān)注創(chuàng)新互聯(lián)行業(yè)資訊頻道了解更多相關(guān)知識(shí)。
網(wǎng)站標(biāo)題:Go語(yǔ)言中如何理解協(xié)程通信實(shí)現(xiàn)的消息傳遞篇
當(dāng)前鏈接:http://muchs.cn/article28/gjsejp.html
成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供品牌網(wǎng)站建設(shè)、App開發(fā)、虛擬主機(jī)、搜索引擎優(yōu)化、手機(jī)網(wǎng)站建設(shè)、移動(dòng)網(wǎng)站建設(shè)
聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請(qǐng)盡快告知,我們將會(huì)在第一時(shí)間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如需處理請(qǐng)聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來源: 創(chuàng)新互聯(lián)