Go学习打卡Day09 并发编程—goroutine

144 阅读2分钟

一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第9天,点击查看活动详情

Go学习打卡Day09 并发编程—goroutine

1、基础概念

  • goroutine是Go中的协程,它是一种轻量化的线程,比起线程它耗费更少的资源,由 Go 运行时(runtime)管理。Go 程序会智能地将 goroutine 中的任务合理地分配给每个 CPU。
  • Go 程序从 main 包的 main() 函数开始,在程序启动时,Go 程序就会为 main() 函数创建一个默认的 goroutine。
  • 并发 多个任务跑在一个cpu上,在某一时刻只处理一个任务,任务之间来回切换的时间极短。
  • 并行 多个任务跑在多个cpu上,在某一时刻多个cpu处理多个任务,达到并行的效果

2、创建goroutine

Go 程序中使用 go 关键字为一个函数创建一个 goroutine。一个函数可以被创建多个 goroutine,一个 goroutine 必定对应一个函数。

  • go 函数名( 参数列表 )
  • 函数名:要调用的函数名。
  • 参数列表:调用函数需要传入的参数。
  • 使用 go 关键字创建 goroutine 时,被调用函数的返回值会被忽略。
  • 如果需要在 goroutine 中返回数据,请使用后面介绍的通道(channel)特性,通过通道把数据从 goroutine 中作为返回值传出。
package main
​
import (
    "fmt"
)
​
func hello() {
    fmt.Println("Hello")
}
​
func main() {
    go hello()
    fmt.Println("Hi")
}
//Hi

分析:main 函数退出太快,另外一个 goroutine 中的函数还未执行完程序就退出了,导致未打印出“Hello”。

package main
​
import (
    "fmt"
    "sync"
)
​
var wg sync.WaitGroup
​
func hello() {
    fmt.Println("Hello")
    wg.Done() //通知goroutine当前函数已完成
}
​
func main() {
    wg.Add(1) //注册一个goroutine
    go hello()
    fmt.Println("Hi")
    wg.Wait() //阻塞并等待已注册的goroutine完成
}
//Hi
//Hello

3、创建多个goroutine

package main
​
import (
    "fmt"
    "sync"
)
​
var wg sync.WaitGroup
​
func hello(i int) {
    defer wg.Done()
    fmt.Println("Hi", i)
}
func main() {
    for i := 0; i < 5; i++ {
        wg.Add(1)
        go hello(i)
    }
    wg.Wait()
}
/*
Hi 3
Hi 1
Hi 0
Hi 4
Hi 2
*/

4、GOMAXPROCS

Go运行时的调度器使用GOMAXPROCS参数来确定需要使用多少个 OS 线程来同时执行 Go 代码。默认值是机器上的 CPU 核心数。例如在一个 8 核心的机器上,GOMAXPROCS 默认为 8。Go语言中可以通过runtime.GOMAXPROCS函数设置当前程序并发时占用的 CPU逻辑核心数。