1. <strong id="7actg"></strong>
    2. <table id="7actg"></table>

    3. <address id="7actg"></address>
      <address id="7actg"></address>
      1. <object id="7actg"><tt id="7actg"></tt></object>

        在 Go 語(yǔ)言中管理 Concurrency 的三種方式

        共 1333字,需瀏覽 3分鐘

         ·

        2020-08-12 02:06

        點(diǎn)擊上方藍(lán)色“Go語(yǔ)言中文網(wǎng)”關(guān)注我們,領(lǐng)全套Go資料,每天學(xué)習(xí)?Go?語(yǔ)言

        相信大家踏入 Go 語(yǔ)言的世界,肯定是被強(qiáng)大的并發(fā)(Concurrency)所吸引,Go 語(yǔ)言用最簡(jiǎn)單的關(guān)鍵字go就可以將任務(wù)丟到后臺(tái)處理,但是開發(fā)者怎么有效率的控制并發(fā),這是入門 Go 語(yǔ)言必學(xué)的技能,本章會(huì)介紹幾種方式來(lái)帶大家認(rèn)識(shí)并發(fā),而這三種方式分別對(duì)應(yīng)到三個(gè)不同的名詞:WaitGroup,Channel,及 Context。下面用簡(jiǎn)單的范例帶大家了解。

        WaitGroup

        先來(lái)了解有什么情境需要使用到 WaitGroup,假設(shè)您有兩臺(tái)機(jī)器需要同時(shí)上傳最新的代碼,兩臺(tái)機(jī)器分別上傳完成后,才能執(zhí)行最后的重啟步驟。就像是把一個(gè)工作同時(shí)拆成好幾份同時(shí)一起做,可以減少時(shí)間,但是最后需要等到全部做完,才能執(zhí)行下一步,這時(shí)候就需要用到 WaitGroup 才能做到。

        package?main

        import?(
        ????"fmt"
        ????"sync"
        )

        func?main()?{
        ????var?wg?sync.WaitGroup
        ????i?:=?0
        ????wg.Add(3)?//task?count?wait?to?do
        ????go?func()?{
        ????????defer?wg.Done()?//?finish?task1
        ????????fmt.Println("goroutine?1?done")
        ????????i++
        ????}()
        ????go?func()?{
        ????????defer?wg.Done()?//?finish?task2
        ????????fmt.Println("goroutine?2?done")
        ????????i++
        ????}()
        ????go?func()?{
        ????????defer?wg.Done()?//?finish?task3
        ????????fmt.Println("goroutine?3?done")
        ????????i++
        ????}()
        ????wg.Wait()?//?wait?for?tasks?to?be?done
        ????fmt.Println("all?goroutine?done")
        ????fmt.Println(i)
        }

        Channel

        另外一種實(shí)際的案例就是,我們需要主動(dòng)通知一個(gè) Goroutine 進(jìn)行停止的動(dòng)作。換句話說(shuō),當(dāng) App 啟動(dòng)時(shí),會(huì)在后臺(tái)跑一些監(jiān)控程序,而當(dāng)整個(gè) App 需要停止前,需要發(fā)個(gè) Notification 給后臺(tái)的監(jiān)控程序,將其先停止,這時(shí)候就需要用到 Channel 來(lái)通知??聪孪旅孢@個(gè)例子:

        package?main

        import?(
        ????"fmt"
        ????"time"
        )

        func?main()?{
        ????exit?:=?make(chan?bool)
        ????go?func()?{
        ????????for?{
        ????????????select?{
        ????????????case?<-exit:
        ????????????????fmt.Println("Exit")
        ????????????????return
        ????????????case?<-time.After(2?*?time.Second):
        ????????????????fmt.Println("Monitoring")
        ????????????}
        ????????}
        ????}()
        ????time.Sleep(5?*?time.Second)
        ????fmt.Println("Notify?Exit")
        ????exit?<-?true?//keep?main?goroutine?alive
        ????time.Sleep(5?*?time.Second)
        }

        上面的例子可以發(fā)現(xiàn),用了一個(gè) Gogourtine 和 Channel 來(lái)控制。可以想像當(dāng)后臺(tái)有無(wú)數(shù)個(gè) Goroutine 的時(shí)候,我們就需要用多個(gè) Channel 才能進(jìn)行控制,也許 Goroutine 內(nèi)又會(huì)產(chǎn)生 Goroutine,開發(fā)者這時(shí)候就會(huì)發(fā)現(xiàn)已經(jīng)無(wú)法單純使用 Channel 來(lái)控制多個(gè) Goroutine 了。這時(shí)候解決方式會(huì)是傳遞 Context。

        Context

        大家可以想像,今天有一個(gè)后臺(tái)任務(wù) A,A 任務(wù)又產(chǎn)生了 B 任務(wù),B 任務(wù)又產(chǎn)生了 C 任務(wù),也就是可以按照此模式一直產(chǎn)生下去,假設(shè)中途我們需要停止 A 任務(wù),而 A 又必須告訴 B 及 C 要一起停止,這時(shí)候通過 context 方式是最快的了。

        package?main

        import?(
        ????"context"
        ????"fmt"
        ????"time"
        )

        func?foo(ctx?context.Context,?name?string)?{
        ????go?bar(ctx,?name)?//?A?calls?B
        ????for?{
        ????????select?{
        ????????case?<-ctx.Done():
        ????????????fmt.Println(name,?"A?Exit")
        ????????????return
        ????????case?<-time.After(1?*?time.Second):
        ????????????fmt.Println(name,?"A?do?something")
        ????????}
        ????}
        }

        func?bar(ctx?context.Context,?name?string)?{
        ????for?{
        ????????select?{
        ????????case?<-ctx.Done():
        ????????????fmt.Println(name,?"B?Exit")
        ????????????return
        ????????case?<-time.After(2?*?time.Second):
        ????????????fmt.Println(name,?"B?do?something")
        ????????}
        ????}
        }

        func?main()?{
        ????ctx,?cancel?:=?context.WithCancel(context.Background())
        ????go?foo(ctx,?"FooBar")
        ????fmt.Println("client?release?connection,?need?to?notify?A,?B?exit")
        ????time.Sleep(5?*?time.Second)
        ????cancel()?//mock?client?exit,?and?pass?the?signal,?ctx.Done()?gets?the?signal??time.Sleep(3?*?time.Second)
        ????time.Sleep(3?*?time.Second)
        }

        大家可以把 context 想成是一個(gè) controller,可以隨時(shí)控制不確定個(gè)數(shù)的 Goroutine,由上往下,只要宣告context.WithCancel后,再任意時(shí)間點(diǎn)都可以通過cancel()來(lái)停止整個(gè)后臺(tái)服務(wù)。實(shí)際案例會(huì)用在當(dāng) App 需要重新啟動(dòng)時(shí),要先通知全部 goroutine 停止,正常停止后,才會(huì)重新啟動(dòng) App。

        總結(jié)

        根據(jù)不同的情境跟狀況來(lái)選擇不同的方式,做一個(gè)總結(jié):

        • WaitGroup:需要將單一個(gè)工作分解成多個(gè)子任務(wù),等到全部完成后,才能進(jìn)行下一步,這時(shí)候用 WaitGroup 最適合了
        • Channel + Select:Channel 只能用在比較單純的 Goroutine 情況下,如果要管理多個(gè) Goroutine,建議還是 走 context 會(huì)比較適合
        • Context:如果您想一次控制全部的 Goroutine,相信用 context 會(huì)是最適合不過的,當(dāng)然 context 不只有這特性,詳細(xì)可以參考『用 10 分鐘了解 Go 語(yǔ)言 context package 使用場(chǎng)景及介紹

        作者:AppleBOY

        原文鏈接:https://blog.wu-boy.com/2020/08/three-ways-to-manage-concurrency-in-go/



        推薦閱讀


        學(xué)習(xí)交流 Go 語(yǔ)言,掃碼回復(fù)「進(jìn)群」即可


        站長(zhǎng) polarisxu

        自己的原創(chuàng)文章

        不限于 Go 技術(shù)

        職場(chǎng)和創(chuàng)業(yè)經(jīng)驗(yàn)


        Go語(yǔ)言中文網(wǎng)

        每天為你

        分享 Go 知識(shí)

        Go愛好者值得關(guān)注


        瀏覽 26
        點(diǎn)贊
        評(píng)論
        收藏
        分享

        手機(jī)掃一掃分享

        分享
        舉報(bào)
        評(píng)論
        圖片
        表情
        推薦
        點(diǎn)贊
        評(píng)論
        收藏
        分享

        手機(jī)掃一掃分享

        分享
        舉報(bào)
        1. <strong id="7actg"></strong>
        2. <table id="7actg"></table>

        3. <address id="7actg"></address>
          <address id="7actg"></address>
          1. <object id="7actg"><tt id="7actg"></tt></object>
            探花导航| 成人三级片在线 | 黄网视频免费观看 | 艹逼视频免费 | 俺去也视频 | 成人视频在线观看 | 国产玩逼| 日本A V网站 | 日本一二三在线播放 | 无码一区二区三区四区五区 |