開心檔之Go 并發(fā)

Go 并發(fā)

Go 語言支持并發(fā),我們只需要通過 go 關(guān)鍵字來開啟 goroutine 即可搀军。

goroutine 是輕量級線程破托,goroutine 的調(diào)度是由 Golang 運行時進行管理的铝阐。

goroutine 語法格式:

go函數(shù)名( 參數(shù)列表 )

例如:

gof(x, y, z)

開啟一個新的 goroutine:

f(x, y, z)

Go 允許使用 go 語句開啟一個新的運行期線程屉更, 即 goroutine,以一個不同的、新創(chuàng)建的 goroutine 來執(zhí)行一個函數(shù)舍扰。 同一個程序中的所有 goroutine 共享同一個地址空間。

實例

package main

import (

"fmt"

"time"

)

func say(s string) {

for i := 0; i < 5; i++ {

time.Sleep(100 * time.Millisecond)

fmt.Println(s)

}

}

func main() {

go say("world")

say("hello")

}

執(zhí)行以上代碼希坚,你會看到輸出的 hello 和 world 是沒有固定先后順序边苹。因為它們是兩個 goroutine 在執(zhí)行:

world

hello

hello

world

world

hello

hello

world

world

hello

通道(channel)

通道(channel)是用來傳遞數(shù)據(jù)的一個數(shù)據(jù)結(jié)構(gòu)。

通道可用于兩個 goroutine 之間通過傳遞一個指定類型的值來同步運行和通訊裁僧。操作符?<-?用于指定通道的方向个束,發(fā)送或接收。如果未指定方向聊疲,則為雙向通道茬底。

ch <- v// 把 v 發(fā)送到通道 chv := <-ch// 從 ch 接收數(shù)據(jù)// 并把值賦給 v

聲明一個通道很簡單,我們使用chan關(guān)鍵字即可获洲,通道在使用前必須先創(chuàng)建:

ch :=make(chanint)

注意:默認情況下阱表,通道是不帶緩沖區(qū)的。發(fā)送端發(fā)送數(shù)據(jù)贡珊,同時必須有接收端相應(yīng)的接收數(shù)據(jù)最爬。

以下實例通過兩個 goroutine 來計算數(shù)字之和,在 goroutine 完成計算后门岔,它會計算兩個結(jié)果的和:

實例

package main

import "fmt"

func sum(s []int, c chan int) {

sum := 0

for _, v := range s {

sum += v

}

c <- sum // 把 sum 發(fā)送到通道 c

}

func main() {

s := []int{7, 2, 8, -9, 4, 0}

c := make(chan int)

go sum(s[:len(s)/2], c)

go sum(s[len(s)/2:], c)

x, y := <-c, <-c // 從通道 c 中接收

fmt.Println(x, y, x+y)

}

輸出結(jié)果為:

-5 17 12

通道緩沖區(qū)

通道可以設(shè)置緩沖區(qū)爱致,通過 make 的第二個參數(shù)指定緩沖區(qū)大小:

ch :=make(chanint,100)

帶緩沖區(qū)的通道允許發(fā)送端的數(shù)據(jù)發(fā)送和接收端的數(shù)據(jù)獲取處于異步狀態(tài)寒随,就是說發(fā)送端發(fā)送的數(shù)據(jù)可以放在緩沖區(qū)里面糠悯,可以等待接收端去獲取數(shù)據(jù)帮坚,而不是立刻需要接收端去獲取數(shù)據(jù)。

不過由于緩沖區(qū)的大小是有限的互艾,所以還是必須有接收端來接收數(shù)據(jù)的试和,否則緩沖區(qū)一滿,數(shù)據(jù)發(fā)送端就無法再發(fā)送數(shù)據(jù)了忘朝。

注意:如果通道不帶緩沖灰署,發(fā)送方會阻塞直到接收方從通道中接收了值判帮。如果通道帶緩沖局嘁,發(fā)送方則會阻塞直到發(fā)送的值被拷貝到緩沖區(qū)內(nèi);如果緩沖區(qū)已滿晦墙,則意味著需要等待直到某個接收方獲取到一個值悦昵。接收方在有值可以接收之前會一直阻塞。

實例

package main

import "fmt"

func main() {

// 這里我們定義了一個可以存儲整數(shù)類型的帶緩沖通道

// 緩沖區(qū)大小為2

ch := make(chan int, 2)

// 因為 ch 是帶緩沖的通道晌畅,我們可以同時發(fā)送兩個數(shù)據(jù)

// 而不用立刻需要去同步讀取數(shù)據(jù)

ch <- 1

ch <- 2

// 獲取這兩個數(shù)據(jù)

fmt.Println(<-ch)

fmt.Println(<-ch)

}

執(zhí)行輸出結(jié)果為:

1

2

Go 遍歷通道與關(guān)閉通道

Go 通過 range 關(guān)鍵字來實現(xiàn)遍歷讀取到的數(shù)據(jù)但指,類似于與數(shù)組或切片。格式如下:

v, ok := <-ch

如果通道接收不到數(shù)據(jù)后 ok 就為 false抗楔,這時通道就可以使用 close() 函數(shù)來關(guān)閉棋凳。

實例

package main

import (

"fmt"

)

func fibonacci(n int, c chan int) {

x, y := 0, 1

for i := 0; i < n; i++ {

c <- x

x, y = y, x+y

}

close(c)

}

func main() {

c := make(chan int, 10)

go fibonacci(cap(c), c)

// range 函數(shù)遍歷每個從通道接收到的數(shù)據(jù),因為 c 在發(fā)送完 10 個

// 數(shù)據(jù)之后就關(guān)閉了通道连躏,所以這里我們 range 函數(shù)在接收到 10 個數(shù)據(jù)

// 之后就結(jié)束了剩岳。如果上面的 c 通道不關(guān)閉,那么 range 函數(shù)就不

// 會結(jié)束入热,從而在接收第 11 個數(shù)據(jù)的時候就阻塞了拍棕。

for i := range c {

fmt.Println(i)

}

}

執(zhí)行輸出結(jié)果為:

0

1

1

2

3

5

8

13

21

34

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市勺良,隨后出現(xiàn)的幾起案子绰播,更是在濱河造成了極大的恐慌,老刑警劉巖尚困,帶你破解...
    沈念sama閱讀 206,126評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件蠢箩,死亡現(xiàn)場離奇詭異,居然都是意外死亡事甜,警方通過查閱死者的電腦和手機忙芒,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,254評論 2 382
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來讳侨,“玉大人呵萨,你說我怎么就攤上這事】缈纾” “怎么了潮峦?”我有些...
    開封第一講書人閱讀 152,445評論 0 341
  • 文/不壞的土叔 我叫張陵囱皿,是天一觀的道長。 經(jīng)常有香客問我忱嘹,道長嘱腥,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 55,185評論 1 278
  • 正文 為了忘掉前任拘悦,我火速辦了婚禮齿兔,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘础米。我一直安慰自己分苇,他們只是感情好,可當我...
    茶點故事閱讀 64,178評論 5 371
  • 文/花漫 我一把揭開白布屁桑。 她就那樣靜靜地躺著医寿,像睡著了一般。 火紅的嫁衣襯著肌膚如雪蘑斧。 梳的紋絲不亂的頭發(fā)上靖秩,一...
    開封第一講書人閱讀 48,970評論 1 284
  • 那天,我揣著相機與錄音竖瘾,去河邊找鬼沟突。 笑死,一個胖子當著我的面吹牛捕传,可吹牛的內(nèi)容都是我干的惠拭。 我是一名探鬼主播,決...
    沈念sama閱讀 38,276評論 3 399
  • 文/蒼蘭香墨 我猛地睜開眼乐横,長吁一口氣:“原來是場噩夢啊……” “哼求橄!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起葡公,我...
    開封第一講書人閱讀 36,927評論 0 259
  • 序言:老撾萬榮一對情侶失蹤蒲祈,失蹤者是張志新(化名)和其女友劉穎凭语,沒想到半個月后极舔,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體镊屎,經(jīng)...
    沈念sama閱讀 43,400評論 1 300
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 35,883評論 2 323
  • 正文 我和宋清朗相戀三年蒲凶,在試婚紗的時候發(fā)現(xiàn)自己被綠了气筋。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 37,997評論 1 333
  • 序言:一個原本活蹦亂跳的男人離奇死亡旋圆,死狀恐怖宠默,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情灵巧,我是刑警寧澤搀矫,帶...
    沈念sama閱讀 33,646評論 4 322
  • 正文 年R本政府宣布抹沪,位于F島的核電站,受9級特大地震影響瓤球,放射性物質(zhì)發(fā)生泄漏融欧。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 39,213評論 3 307
  • 文/蒙蒙 一卦羡、第九天 我趴在偏房一處隱蔽的房頂上張望噪馏。 院中可真熱鬧,春花似錦绿饵、人聲如沸欠肾。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,204評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽董济。三九已至步清,卻和暖如春要门,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背廓啊。 一陣腳步聲響...
    開封第一講書人閱讀 31,423評論 1 260
  • 我被黑心中介騙來泰國打工欢搜, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人谴轮。 一個月前我還...
    沈念sama閱讀 45,423評論 2 352
  • 正文 我出身青樓炒瘟,卻偏偏與公主長得像,于是被迫代替她去往敵國和親第步。 傳聞我的和親對象是個殘疾皇子疮装,可洞房花燭夜當晚...
    茶點故事閱讀 42,722評論 2 345

推薦閱讀更多精彩內(nèi)容