over-golang/02-并发编程/01-goroutine.md
2021-07-02 18:11:59 +08:00

3.1 KiB
Raw Permalink Blame History

一 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