千家信息网

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

发表于:2025-01-17 作者:千家信息网编辑
千家信息网最后更新 2025年01月17日,这篇文章主要讲解了"Go语言中管理Concurrency的方式有哪些",文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习"Go语言中管理Concurrency
千家信息网最后更新 2025年01月17日Go语言中管理Concurrency的方式有哪些

这篇文章主要讲解了"Go语言中管理Concurrency的方式有哪些",文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习"Go语言中管理Concurrency的方式有哪些"吧!

WaitGroup

先来了解有什么情境需要使用到 WaitGroup,假设您有两台机器需要同时上传最新的代码,两台机器分别上传完成后,才能执行最后的重启步骤。就像是把一个工作同时拆成好几份同时一起做,可以减少时间,但是最后需要等到全部做完,才能执行下一步,这时候就需要用到 WaitGroup 才能做到。

package mainimport (    "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 启动时,会在后台跑一些监控程序,而当整个 App 需要停止前,需要发个 Notification 给后台的监控程序,将其先停止,这时候就需要用到 Channel 来通知。看下下面这个例子:

package mainimport (    "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)}

上面的例子可以发现,用了一个 GogourtineChannel 来控制。可以想像当后台有无数个 Goroutine 的时候,我们就需要用多个 Channel 才能进行控制,也许 Goroutine 内又会产生 Goroutine,开发者这时候就会发现已经无法单纯使用 Channel 来控制多个 Goroutine 了。这时候解决方式会是传递 Context

Context

大家可以想像,今天有一个后台任务 A,A 任务又产生了 B 任务,B 任务又产生了 C 任务,也就是可以按照此模式一直产生下去,假设中途我们需要停止 A 任务,而 A 又必须告诉 B 及 C 要一起停止,这时候通过 context 方式是最快的了。

package mainimport (    "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 mainimport (    "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的方式有哪些这一问题有了更深刻的体会,具体使用情况还需要大家实践验证。这里是,小编将为大家推送更多相关知识点的文章,欢迎关注!

0