溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊(cè)×
其他方式登錄
點(diǎn)擊 登錄注冊(cè) 即表示同意《億速云用戶服務(wù)條款》

golang中的并發(fā)是怎么實(shí)現(xiàn)的

發(fā)布時(shí)間:2020-06-24 11:40:54 來(lái)源:億速云 閱讀:120 作者:Leah 欄目:編程語(yǔ)言

golang中的并發(fā)是怎么實(shí)現(xiàn)的?可能很多人都不太了解,為了讓大家更加了解,小編給大家總結(jié)了以下內(nèi)容,希望大家根據(jù)這篇文章可以有所收獲。

Go中并發(fā)程序依靠的是兩個(gè):goroutine和channel

理解什么是goroutine?

對(duì)于初學(xué)者,goroutine直接理解成為線程就可以了。當(dāng)對(duì)一個(gè)函數(shù)調(diào)用go,啟動(dòng)一個(gè)goroutine的時(shí)候,就相當(dāng)于起來(lái)一個(gè)線程,執(zhí)行這個(gè)函數(shù)。

實(shí)際上,一個(gè)goroutine并不相當(dāng)于一個(gè)線程,goroutine的出現(xiàn)正是為了替代原來(lái)的線程概念成為最小的調(diào)度單位。

一旦運(yùn)行g(shù)oroutine時(shí),先去當(dāng)先線程查找,如果線程阻塞了,則被分配到空閑的線程,如果沒(méi)有空閑的線程,那么就會(huì)新建一個(gè)線程。注意的是,當(dāng)goroutine執(zhí)行完畢后,線程不會(huì)回收推出,而是成為了空閑的線程。

goroutine的使用

使用非常簡(jiǎn)單,在函數(shù)前增加一個(gè)go

f(11)

go f(11) //這個(gè)是讓f()函數(shù)作為goroutine運(yùn)行

但是go有一個(gè)缺點(diǎn),主線程要等待一個(gè)goroutine結(jié)束再處理怎么辦?拿《學(xué)習(xí)go語(yǔ)言》中的一個(gè)例子說(shuō)明。

golang中的并發(fā)是怎么實(shí)現(xiàn)的

這里的第18行為什么要sleep? 這里是為了等上面兩個(gè)go ready處理完成。

好了,這里就出來(lái)了一個(gè)需求:一個(gè)goroutine結(jié)束后必須要向主線程傳輸數(shù)據(jù),告訴主線程這個(gè)goroutine已經(jīng)結(jié)束了。

這里就引進(jìn)了channel的概念

channel的使用

channel的意思用白話可以這么理解:主線程告訴大家你開(kāi)goroutine可以,但是我在我的主線程開(kāi)了一個(gè)管道,你做完了你要做的事情之后,往管道里面塞個(gè)東西告訴我你已經(jīng)完成了。

上面的例子就可以改為:

golang中的并發(fā)是怎么實(shí)現(xiàn)的

從這個(gè)程序得到的幾點(diǎn)信息:

1 channel只能使用make來(lái)進(jìn)行創(chuàng)建

基本格式是 c := make(chan int)

int是說(shuō)明這個(gè)管道能傳輸什么類型的數(shù)據(jù)

2 往channel中插入數(shù)據(jù)的操作

c <- 1

是不是很形象

3 從channel中輸出數(shù)據(jù)

<- c

4 為什么需要輸出兩次(4和5兩行?)

因?yàn)?和3啟動(dòng)了兩個(gè)goroutine,每個(gè)goroutine都往管道輸出一個(gè)1,因此主線程要接收兩次才能說(shuō)明兩個(gè)goroutine都結(jié)束了

channel的進(jìn)一步理解:

channel分為兩種:一種是有buffer的,一種是沒(méi)有buffer的,默認(rèn)是沒(méi)有buffer的

ci := make(chan int) //無(wú)buffer

cj := make(chan int, 0) //無(wú)buffer

cs := make(chan int, 100) //有buffer

有緩沖的channel,因此要注意“放”先于“取”

無(wú)緩沖的channel,因此要注意“取”先于“放”

同樣要先輸出hello world,使用有緩沖的channel和無(wú)緩沖的channel分別是這樣的:

有緩沖的channel:

var a string
var c = make(chan int, 10)
  
func f() {
    a = "hello, world"
    c <- 0
}
  
func main() {
    go f()
    <-c
    print(a)
 
}

這里有個(gè)緩沖,因此放入數(shù)據(jù)的操作c<- 0先于取數(shù)據(jù)操作 <-c

無(wú)緩沖的channel:

var a string
var c = make(chan int)
  
func f() {
    a = "hello, world"
    <-c
}
  
func main() {
    go f()
    c <- 0
    print(a)
 
}

由于c是無(wú)緩沖的channel,因此必須保證取操作<-c 先于放操作c<- 0

看完上述內(nèi)容,你們對(duì)golang中的并發(fā)實(shí)現(xiàn)有進(jìn)一步的了解嗎?如果還想了解更多相關(guān)內(nèi)容,歡迎關(guān)注億速云行業(yè)資訊頻道,感謝各位的閱讀。

向AI問(wèn)一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI