Golang并发控制基本的三种方式

并发执行在Golang中很容易实现,只需要go func(),大多数我们会把一个大的任务拆分成多个子任务去执行,这时候我们就需要关心子任务是否执行成功和结束,需要收到信息进行下一步程序的执行。在golang中,我整理了三种Goroutine常用的控制方式。
1:Sync.WaitGroup:

package main

import (
    "context"
    "fmt"
    "net/http"
    "sync"
    "time"
)

func main() {
    var wg sync.WaitGroup
    //2个task
    wg.Add(2)
    go func() {
        defer wg.Done()
        fmt.Println("goroutine 1 done")

    }()
    go func() {
        defer wg.Done()
        fmt.Println("goroutine 2 done")

    }()

    wg.Wait()
    fmt.Println("all goroutine done")
}

2:Channel

package main

import (
    "context"
    "fmt"
    "net/http"
    "sync"
    "time"
)

func main() {
    ch := make(chan int)
    flag := make(chan bool)
    go son(ch, flag)

    for i := 0; i < 10; i++ {
        ch <- i
    }
    flag <- true
    fmt.Println("all is over")

}

func son(ch chan int, flag chan bool) {
    t := time.Tick(time.Second)
    for _ = range t {
        select {
        case msg := <-ch:
            fmt.Println("print", msg)
        case <-flag:
            fmt.Println("goroutine is over")
        }
    }

}

使用场景:当一个主任务拆分为子任务去执行,子任务全部执行完毕,通过channel来通知主任务执行完毕,主任务继续向下执行。比较适用于层级比较少的主任务和子任务间的通信。
3:Context

package main

import (
    "context"
    "fmt"
    "net/http"
    "sync"
    "time"
)

func main() {
    ctx, cancel := context.WithCancel(context.Background())
    go foo(ctx, "Sonbar")
    fmt.Println("subwork is starting")
    time.Sleep(5 * time.Second)
    //fiveminutes is over
    cancel()
    //allgoroutine over
    time.Sleep(3 * time.Second)
    fmt.Println("main work over")
}

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

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

使用场景:适用于多层Goroutine嵌套和组合,当然Context包不仅仅用于并发控制,还有更多的功能和场景需要我们去探索。

你可能感兴趣的:(golang后端)