溫馨提示×

溫馨提示×

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

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

Go語言中管理Concurrency的方式有哪些

發(fā)布時間:2022-02-25 10:05:15 來源:億速云 閱讀:120 作者:iii 欄目:開發(fā)技術

這篇文章主要講解了“Go語言中管理Concurrency的方式有哪些”,文中的講解內容簡單清晰,易于學習與理解,下面請大家跟著小編的思路慢慢深入,一起來研究和學習“Go語言中管理Concurrency的方式有哪些”吧!

WaitGroup

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

另外一種實際的案例就是,我們需要主動通知一個 Goroutine 進行停止的動作。換句話說,當 App 啟動時,會在后臺跑一些監(jiān)控程序,而當整個 App 需要停止前,需要發(fā)個 Notification 給后臺的監(jiān)控程序,將其先停止,這時候就需要用到 Channel 來通知。看下下面這個例子:

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ā)現,用了一個 GogourtineChannel 來控制??梢韵胂癞敽笈_有無數個 Goroutine 的時候,我們就需要用多個 Channel 才能進行控制,也許 Goroutine 內又會產生 Goroutine,開發(fā)者這時候就會發(fā)現已經無法單純使用 Channel 來控制多個 Goroutine 了。這時候解決方式會是傳遞 Context

Context

大家可以想像,今天有一個后臺任務 A,A 任務又產生了 B 任務,B 任務又產生了 C 任務,也就是可以按照此模式一直產生下去,假設中途我們需要停止 A 任務,而 A 又必須告訴 B 及 C 要一起停止,這時候通過 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)
}
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 想成是一個 controller,可以隨時控制不確定個數的 Goroutine,由上往下,只要宣告context.WithCancel后,再任意時間點都可以通過cancel()來停止整個后臺服務。實際案例會用在當 App 需要重新啟動時,要先通知全部 goroutine 停止,正常停止后,才會重新啟動 App。

感謝各位的閱讀,以上就是“Go語言中管理Concurrency的方式有哪些”的內容了,經過本文的學習后,相信大家對Go語言中管理Concurrency的方式有哪些這一問題有了更深刻的體會,具體使用情況還需要大家實踐驗證。這里是億速云,小編將為大家推送更多相關知識點的文章,歡迎關注!

向AI問一下細節(jié)

免責聲明:本站發(fā)布的內容(圖片、視頻和文字)以原創(chuàng)、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI