一起养成写作习惯!这是我参与「掘金日新计划 · 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逻辑核心数。