goroutine协程创建和使用

发布时间 2023-04-07 22:55:34作者: yangphp

前言:

协程的创建和使用,Go语言中使用goroutine非常简单,

只需要在调用函数的时候在前面加上go关键字,就可以为一个函数创建一个goroutine

 

正文:

 

函数创建goroutine语法:

go 函数名( 参数列表 )

函数名:要调用的函数名。

参数列表:调用函数需要传入的参数。

 

 

goroutine 实例1:

func test() {

fmt.Println("test()", "hello test")

}

main调用:

go test() //增加go关键字,将test函数变为一个协程

fmt.Println("main()", "hello main")

//需要等待协程执行,不等待的话,有可能协程没有执行,程序就退出了

time.Sleep(time.Second)  

 

主程序main,执行完毕,所有开启的协程,也全部退出。所有有时候看到协程,并不会全部执行完毕。

 

goroutine执行流程

 

 

Runtime GOMAXPROCS

Go运行时的调度器使用GOMAXPROCS参数来确定需要使用多少个OS线程来同时执行Go代码。

默认值是机器上的CPU核心数。

 

使用 runtime.NumCPU() 查询 CPU 数量

使用 runtime.GOMAXPROCS() 函数进行设置当前程序并发时占用的CPU逻辑核心数。

使用 runtime.NumGoroutine() 返回正在执行和排队的任务总数

使用:runtime.Gosched()  让出CPU时间片,重新等待安排任务

使用:runtime.Goexit()  退出当前 goroutine,不执行

 

多个goroutine交替执行示例:

两个协程交替执行

Go1.5版本之前,默认使用的是单核心执行。

Go1.5版本之后,默认使用全部的CPU逻辑核心

 

func test1() {
    for i := 1; i < 10; i++ {
        fmt.Println("test1()", i)
    }
}
func test2() {
    for i := 1; i < 10; i++ {
        fmt.Println("test2()", i)
    }
}

func main()  {
    runtime.GOMAXPROCS(1) //设置使用的cpu核心数,默认是全部核心
    go test1()
    go test2()
    //查看CPU数量
    fmt.Println(runtime.NumCPU())
    //查看正在执行和排队的协程总数 ,输出3
    fmt.Println(runtime.NumGoroutine())

    fmt.Println("main()", "hello main")
    time.Sleep(time.Second) //等待协程执行
}

 

 

sync.WaitGroup使用

 

当某个操作或是某个goroutine需要等待一批goroutine执行完毕以后才继续执行,

那么这种多线程(go里面说的线程就是goroutine)等待的问题就可以使用WaitGroup  

使用sync.WaitGroup来实现并发任务的同步

 

地址:https://go-zh.org/pkg/sync/

waitGroup实例1

需要等待一批协程执行完毕,才可以执行后续操作,就无须使用 time.sleep函数,进行等待

var wg = sync.WaitGroup{} //WaitGroup初始化
func test1() {
    defer wg.Done()  //计数器减一
    for i := 1; i < 10; i++ {
        fmt.Println("test1()", i)
    }
}
func test2() {
    defer wg.Done() //计数器减一
    for i := 1; i < 10; i++ {
        fmt.Println("test2()", i)
    }
}

func main()  {
    wg.Add(2) //计数器设置2,表示创建2个协程等待
    go test1()
    go test2()
    wg.Wait()  //需要等待2个goroutine执行完毕以后才继续执行后续
    fmt.Println("main()", "hello main")
}

 

 

runtime.Gosched

让当前线程让出 cpu 以让其它线程运行,它不会挂起当前线程,

因此当前线程未来会继续执行,在其他协程执行完毕后执行

 

实例1:让出线程,让其他线程运行

var wg = sync.WaitGroup{}
func test(n int) {
    defer wg.Done() 
    if n == 5 {
        runtime.Gosched() 
//让当前线程让出 cpu 以让其它协程运行,
//其他协程执行完毕才能继续运行当前协程
    }
    fmt.Println("test()", n)
}

main:
runtime.GOMAXPROCS(1) //设置使用的cpu核心数
    for i := 0; i < 10; i++ {
        wg.Add(1)
        go test(i)
    }

    wg.Wait()
    fmt.Println("main()", "hello main")

输出结果:test() 5 总是在最后执行

完结