go語(yǔ)言并發(fā)操作

go語(yǔ)言實(shí)現(xiàn)并發(fā)

通過(guò)go 實(shí)現(xiàn)并發(fā)操作
func say(s string) {
for i := 0; i < 5; i++ {
    fmt.Println(s)
}
}

func main(){
    go say("hello")
    say("world")
}

執(zhí)行上述代碼让腹,會(huì)間隔執(zhí)行say方法

通過(guò)channel實(shí)現(xiàn)并發(fā)數(shù)據(jù)間的通信

channel的創(chuàng)建必須通過(guò)make方式實(shí)現(xiàn)

ch := make(chan int)

channel通過(guò)操作符<-接收和發(fā)送數(shù)據(jù)

ch <- value //發(fā)送value到channel ch
value := <-ch //從channel ch中獲取數(shù)據(jù)

下面開(kāi)始是此節(jié)的重點(diǎn)內(nèi)容朝聋,廢話不多說(shuō)先上代碼

代碼1:
func sum(a []int, c chan int) {
    fmt.Println("開(kāi)始往channel中寫數(shù)據(jù)", a)
    total := 0
    for _, v := range a {
        total += v
    }
    c <- total
    fmt.Println("單次寫數(shù)據(jù)處理完成")
}

func main() {
    a := []int{1, 2, 3, 4}

    c := make(chan int)
    fmt.Println("write")
    sum(a[:len(a)/2], c)
    sum(a[len(a)/2:], c)
    fmt.Println("write end")
}
控制臺(tái)輸出:
write
開(kāi)始往channel中寫數(shù)據(jù) [1 2]
單次寫數(shù)據(jù)處理完成
開(kāi)始往channel中寫數(shù)據(jù) [3 4]
fatal error: all goroutines are asleep - deadlock!

程序出現(xiàn)錯(cuò)誤见间,因?yàn)槲覀儎?chuàng)建一個(gè)未指定緩沖大小的channel(當(dāng)未指定緩沖大小時(shí)结序,channel默認(rèn)為0),
我們調(diào)用兩次channel的寫操作预烙,出現(xiàn)了阻塞
代碼2:
func sum(a []int, c chan int) {
    fmt.Println("開(kāi)始往channel中寫數(shù)據(jù)", a)
    total := 0
    for _, v := range a {
        total += v
    }
    fmt.Println("單次寫數(shù)據(jù)處理完成")
    c <- total
}

func main() {
    a := []int{1, 2, 3, 4}

    c := make(chan int, 2)//這里我們指定channel的緩沖為2
    fmt.Println("write")
    sum(a[:len(a)/2], c)
    sum(a[len(a)/2:], c)
    fmt.Println("write end")
}
控制臺(tái)輸出:
write
開(kāi)始往channel中寫數(shù)據(jù) [1 2]
單次寫數(shù)據(jù)處理完成
開(kāi)始往channel中寫數(shù)據(jù) [3 4]
單次寫數(shù)據(jù)處理完成
write end

程序正常結(jié)束正塌,因?yàn)槲覀冎付薱hannel的緩沖大小,所以可以進(jìn)行兩次寫操作
代碼3:
func sum(a []int, c chan int) {
    fmt.Println("開(kāi)始往channel中寫數(shù)據(jù)", a)
    total := 0
    for _, v := range a {
        total += v
    }
    fmt.Println("單次寫數(shù)據(jù)處理完成")
    c <- total
}

func main() {
    a := []int{1, 2, 3, 4}

    c := make(chan int)//如果我們不指定channel的緩沖大小如何實(shí)現(xiàn)兩次寫操作呢
    fmt.Println("write")
    go sum(a[:len(a)/2], c)
    go sum(a[len(a)/2:], c)
    fmt.Println("write end")

}
控制臺(tái)輸出:
write
write end

程序正常結(jié)束呛每,這是因?yàn)槲覀兪褂貌l(fā)調(diào)用調(diào)用sum方法
代碼4:
var (
      wg sync.WaitGroup
)
func sum(a []int, c chan int) {
    fmt.Println("開(kāi)始往channel中寫數(shù)據(jù)", a)
    total := 0
    for _, v := range a {
        total += v
    }
    fmt.Println("單次寫數(shù)據(jù)處理完成")
    c <- total
        wg.Done()
}

func main() {
        wg.Add(2)
    a := []int{1, 2, 3, 4}

    c := make(chan int)
    fmt.Println("write")
    go sum(a[:len(a)/2], c)
    go sum(a[len(a)/2:], c)
    fmt.Println("write end")
        wg.Wait()
}
控制臺(tái)輸出:
fatal error: all goroutines are asleep - deadlock!
write
write end

程序異常踩窖,我們?cè)谥骶€程采用WaitGroup保持主線程不被銷毀,這樣異步線程就有時(shí)間進(jìn)行處理晨横,造成chan阻塞洋腮,代碼4未發(fā)生阻塞,是因?yàn)橹骶€程立刻就結(jié)束
代碼5:
func sum(a []int, c chan int) {
    fmt.Println("開(kāi)始往channel中寫數(shù)據(jù)", a)
    total := 0
    for _, v := range a {
        total += v
    }
    fmt.Println("單次寫數(shù)據(jù)處理完成")
    c <- total
}

func main() {
    a := []int{1, 2, 3, 4}

    c := make(chan int,1)//我們指定channel的緩沖大小為1手形,但是我們調(diào)用兩次寫操作啥供,其中一次為并發(fā)調(diào)用
    fmt.Println("write")
    go sum(a[:len(a)/2], c)
    sum(a[len(a)/2:], c)
    fmt.Println("write end")
    fmt.Println("read x")
    x := <-c
    fmt.Println("x = ", x)
    fmt.Println("read Y")
    y := <-c
    fmt.Println("y = ", y)
    fmt.Println("read end")
}
控制臺(tái)輸出:
write
開(kāi)始往channel中寫數(shù)據(jù) [3 4]
單次寫數(shù)據(jù)處理完成
write end
read x
x =  7
read Y
開(kāi)始往channel中寫數(shù)據(jù) [1 2]
單次寫數(shù)據(jù)處理完成
y =  3
read end

程序正常結(jié)束,可以看到首先執(zhí)行了main線程調(diào)用的sum方法库糠,
然后進(jìn)行一次x值的讀取伙狐,取得的為main線程寫入的數(shù)據(jù),
再進(jìn)行一次y值的讀取瞬欧,先進(jìn)行了數(shù)據(jù)的寫入贷屎,然后返回寫入的值
代碼6:
func sum(a []int, c chan int) {
    fmt.Println("開(kāi)始往channel中寫數(shù)據(jù)", a)
    total := 0
    for _, v := range a {
        total += v
    }
    fmt.Println("單次寫數(shù)據(jù)處理完成")
    c <- total
}

func main() {
    a := []int{1, 2, 3, 4}

    c := make(chan int,2)//我們指定channel的緩沖大小為2
    fmt.Println("write")
    sum(a[:len(a)/2], c)
    sum(a[len(a)/2:], c)
    fmt.Println("write end")
    fmt.Println("read x")
    x := <-c
    fmt.Println("x = ", x)
    fmt.Println("read Y")
    y := <-c
    fmt.Println("y = ", y)
    fmt.Println("read end")
}
控制臺(tái)輸出:
write
開(kāi)始往channel中寫數(shù)據(jù) [1 2]
單次寫數(shù)據(jù)處理完成
開(kāi)始往channel中寫數(shù)據(jù) [3 4]
單次寫數(shù)據(jù)處理完成
write end
read x
x =  3
read Y
y =  7
read end

程序正常結(jié)束,可以看到首先執(zhí)行兩次main線程調(diào)用的sum方法艘虎,然后分別x,y獲取兩次寫入的值
代碼7:
func sum(a []int, c chan int) {
    fmt.Println("開(kāi)始往channel中寫數(shù)據(jù)", a)
    total := 0
    for _, v := range a {
        total += v
    }
    fmt.Println("單次寫數(shù)據(jù)處理完成")
    c <- total
}

func main() {
    a := []int{1, 2, 3, 4}

    c := make(chan int)//我們未指定channel的緩沖大小
    fmt.Println("write")
    go sum(a[:len(a)/2], c)
    go sum(a[len(a)/2:], c)
    fmt.Println("write end")
    fmt.Println("read x")
    x := <-c
    fmt.Println("x = ", x)
    fmt.Println("read Y")
    y := <-c
    fmt.Println("y = ", y)
    fmt.Println("read end")
}
控制臺(tái)輸出:
write
write end
read x
開(kāi)始往channel中寫數(shù)據(jù) [3 4]
單次寫數(shù)據(jù)處理完成
x =  7
read Y
開(kāi)始往channel中寫數(shù)據(jù) [1 2]
單次寫數(shù)據(jù)處理完成
y =  3
read end

程序正常結(jié)束唉侄,可以看到我們異步調(diào)用兩次sum方法,
然后main線程獲取x值野建,輸入第二次異步的日志属划,同時(shí)返回寫入的數(shù)據(jù),
獲取y值贬墩,輸入第一次異步的日志榴嗅,同時(shí)返回寫入的數(shù)據(jù)
通過(guò)range獲取channel數(shù)據(jù)

range獲取channel的數(shù)據(jù)跟普通的<-唯一的區(qū)別在于需要顯形的關(guān)閉channel

close(ch)

廢話不多說(shuō)繼續(xù)上代碼

代碼1:
func fibonacci(n int, c chan int) {
    x, y := 1, 1
    fmt.Println("開(kāi)始往channel中寫數(shù)據(jù)", n)
    for i := 0; i < n; i++ {
        c <- x
        x, y = y, x+y
    }
    fmt.Println("單次寫數(shù)據(jù)處理完成")
}

func main() {
    ch2 := make(chan int)
    fmt.Println("開(kāi)始range的寫操作")
    go fibonacci(10, ch2)
    fmt.Println("寫操作結(jié)束")
    fmt.Println("開(kāi)始range的讀操作")
    for i := range ch2 {
        fmt.Println(i)
    }
    fmt.Println("讀操作結(jié)束")
}
控制臺(tái)輸出:
fatal error: all goroutines are asleep - deadlock!

goroutine 1 [chan receive]:
main.main()
    /Users/cheyongzi/Desktop/data/project/GoDemo/routine/runtime.go:66 +0x242
開(kāi)始range的寫操作
寫操作結(jié)束
開(kāi)始range的讀操作
開(kāi)始接收
1
1
2
3
5
8
13
21
34
55

程序異常退出,這是因?yàn)閞ange獲取channel的數(shù)據(jù)需要顯性的調(diào)用close方法關(guān)閉channel
代碼1:
func fibonacci(n int, c chan int) {
    x, y := 1, 1
    fmt.Println("開(kāi)始往channel中寫數(shù)據(jù)", n)
    for i := 0; i < n; i++ {
        c <- x
        x, y = y, x+y
    }
    close(c)
    fmt.Println("單次寫數(shù)據(jù)處理完成")
}

func main() {
    ch2 := make(chan int)
    fmt.Println("開(kāi)始range的寫操作")
    go fibonacci(10, ch2)//這里如果不采用異步調(diào)用陶舞,則需要在ch2定義的時(shí)候指定緩沖大小嗽测,否則會(huì)報(bào)錯(cuò)
    fmt.Println("寫操作結(jié)束")
    fmt.Println("開(kāi)始range的讀操作")
    for i := range ch2 {
        fmt.Println(i)
    }
    fmt.Println("讀操作結(jié)束")
}
控制臺(tái)輸出:
開(kāi)始range的寫操作
寫操作結(jié)束
開(kāi)始range的讀操作
開(kāi)始接收
1
1
2
3
5
8
13
21
34
55
讀操作結(jié)束

程序正常運(yùn)行
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子唠粥,更是在濱河造成了極大的恐慌疏魏,老刑警劉巖,帶你破解...
    沈念sama閱讀 222,590評(píng)論 6 517
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件晤愧,死亡現(xiàn)場(chǎng)離奇詭異大莫,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)官份,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 95,157評(píng)論 3 399
  • 文/潘曉璐 我一進(jìn)店門只厘,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人舅巷,你說(shuō)我怎么就攤上這事羔味。” “怎么了钠右?”我有些...
    開(kāi)封第一講書人閱讀 169,301評(píng)論 0 362
  • 文/不壞的土叔 我叫張陵赋元,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我飒房,道長(zhǎng)搁凸,這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書人閱讀 60,078評(píng)論 1 300
  • 正文 為了忘掉前任狠毯,我火速辦了婚禮护糖,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘垃你。我一直安慰自己椅文,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 69,082評(píng)論 6 398
  • 文/花漫 我一把揭開(kāi)白布惜颇。 她就那樣靜靜地躺著,像睡著了一般少辣。 火紅的嫁衣襯著肌膚如雪凌摄。 梳的紋絲不亂的頭發(fā)上,一...
    開(kāi)封第一講書人閱讀 52,682評(píng)論 1 312
  • 那天漓帅,我揣著相機(jī)與錄音锨亏,去河邊找鬼。 笑死忙干,一個(gè)胖子當(dāng)著我的面吹牛器予,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播捐迫,決...
    沈念sama閱讀 41,155評(píng)論 3 422
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼乾翔,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起反浓,我...
    開(kāi)封第一講書人閱讀 40,098評(píng)論 0 277
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤萌丈,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后雷则,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體辆雾,經(jīng)...
    沈念sama閱讀 46,638評(píng)論 1 319
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,701評(píng)論 3 342
  • 正文 我和宋清朗相戀三年月劈,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了度迂。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 40,852評(píng)論 1 353
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡猜揪,死狀恐怖英岭,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情湿右,我是刑警寧澤诅妹,帶...
    沈念sama閱讀 36,520評(píng)論 5 351
  • 正文 年R本政府宣布,位于F島的核電站毅人,受9級(jí)特大地震影響吭狡,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜丈莺,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 42,181評(píng)論 3 335
  • 文/蒙蒙 一划煮、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧缔俄,春花似錦弛秋、人聲如沸。這莊子的主人今日做“春日...
    開(kāi)封第一講書人閱讀 32,674評(píng)論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至遏佣,卻和暖如春挖炬,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背状婶。 一陣腳步聲響...
    開(kāi)封第一講書人閱讀 33,788評(píng)論 1 274
  • 我被黑心中介騙來(lái)泰國(guó)打工意敛, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人膛虫。 一個(gè)月前我還...
    沈念sama閱讀 49,279評(píng)論 3 379
  • 正文 我出身青樓草姻,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親稍刀。 傳聞我的和親對(duì)象是個(gè)殘疾皇子撩独,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,851評(píng)論 2 361

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

  • Android 自定義View的各種姿勢(shì)1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 172,322評(píng)論 25 707
  • 官方網(wǎng)站:https://golang.org/標(biāo)準(zhǔn)庫(kù)文檔:https://golang.org/pkg/在線編碼...
    技術(shù)學(xué)習(xí)閱讀 2,327評(píng)論 2 39
  • 本文翻譯自Sameer Ajmani的文章《Go Concurrency Patterns: Pipelines ...
    大蟒傳奇閱讀 3,873評(píng)論 0 15
  • 這愛(ài)情何止卑微 我竟無(wú)言以對(duì) 我的幻想終于揚(yáng)起帆 遠(yuǎn)航 我的思維卻還未上船來(lái) 我是自己的末路客 正在無(wú)聲無(wú)息的祈禱...
    未明花香閱讀 317評(píng)論 2 0
  • 21組 陳子明 2017 年 11月 1日,周2,晴 身修家和 美麗中國(guó) 種子踐行日記 地方 佛山 第54天 # ...
    大山之子Deron閱讀 165評(píng)論 0 0