3.1 KiB
3.1 KiB
一 Golang对协程的支持
Go语言从语言层面原生提供了协程支持,即 goroutine
,执行goroutine只需极少的栈内存(大概是4~5KB),所以Go可以轻松的运行多个并发任务。
Go中以关键字 go
开启协程:
func say(s string) {
for i := 0; i < 3; i++ {
fmt.Println(s)
}
}
func main() {
go say("Go") // 以协程方式执行say函数
say("noGo") // 以普通方式执行say函数
time.Sleep(5 * time.Second) // 睡眠5秒:防止协程未执行完毕,主程序退出
}
上述的程序的打印结果并不是按照顺序的,因为go关键字开启了协程,两个say函数并不是在一个控制流中!
二 goroutine使用案例
2.1 同时执行两件事
func running() {
var times int
for {
times++
fmt.Println("tick:", times)
time.Sleep(time.Second)
}
}
func main() {
go running()
var input string
fmt.Scanln(&input)
}
命令行会不断地输出 tick,同时可以使用 fmt.Scanln()
接受用户输入。两个环节可以同时进行,直到按 Enter键时将输入的内容写入 input变量中井返回,
整个程序终止。
2.2 一道基础面试题
示例一:
for i := 1; i <= 10; i++ {
go func(){
fmt.Println(i) // 全部打印11:因为开启协程也会耗时,协程没有准备好,循环已经走完
}()
}
time.Sleep(time.Second)
示例二:
for i := 1; i <= 10; i++ {
go func(i int){
fmt.Println(i) // 打印无规律数字
}(i)
}
time.Sleep(time.Second)
三 常用API
3.1 GOMAXPROCS() 多核利用
goroutine相关API位于 runtime
包。
如果Go程序要运行在多核上,则可以如下操作,此时可以实现程序的并行执行:
cpuNum := runtime.NumCPU() //获取当前系统的CPU核心数
runtime.GOMAXPROCS(cpuNum) //Go中可以轻松控制使用核心数
贴士:在Go1.5之后,程序已经默认运行在多核上,无需上述设置
3.2 Gosched() 让出时间片
runtime.Gosched()
:用于让出CPU时间片,即让出当前协程的执行权限,调度器可以去安排其他等待的任务运行。示例如下:
func main(){
for i := 1; i <= 10; i++ {
go func(i int){
if i == 5 {
runtime.Gosched() // 协程让出,但并不代表不执行,而是 5永远不会第一输出
}
fmt.Println(i) // 打印一组无规律数字
}(i)
}
time.Sleep(time.Second)
}
贴士:可以理解为接力赛跑:A跑了一段遇到了Gosched接力给B。
3.3 Goexit() 终止当前协程
runtime.Goexit()
:用于立即终止当前协程运行,调度器会确保所有已注册defer延迟调用被执行。
func main(){
for i := 1; i <= 5; i++ {
defer fmt.Println("defer ", i)
go func(i int){
if i == 3 {
runtime.Goexit()
}
fmt.Println(i)
}(i)
}
time.Sleep(time.Second)
}
输出的结果类似于:
4
2
5
1
defer 5
defer 4
defer 3
defer 2
defer 1