在Go语言中并发是通过goroutine实现。goroutine类似于线程,属于用户态线程。Go语言也可以通过channel(管道)与多个goroutine进行通信。
goroutine
goroutine类似于线程,在Go语言中底层分配了一个线程池,因此不需要我们对其进行管理,由Go运行时的routine进行调度。
在Go语言中实现goroutine非常简单,只需要在调用函数前加上go关键字,就可以为该函数创建一个goroutine。因此一个goroutine对应一个函数,多个goroutine可以对应多个函数。
//串行执行
package main
import "fmt"
func hello(){
fmt.Println("Hello")
}
func main(){
hello()
fmt.Println("Hello Main")
}
上述代码是串行执行,执行完一个函数以后才会执行下一个语句,如果想让其能够并发执行,就需要goroutine
func main(){
go hello()
fmt.Println("Hello Main")
}
只需要在调用具体函数的时候,加上一个go关键字即可。
加上关键字以后,在调用具体方法的时候,就不需要主线程进行调用,主线程会继续往下执行,主线程于子线程并发执行。因此执行出来的结果不同。
如果想让全部执行结束以后,再返回。
func main(){
go hello()
fmt.Println("Hello Main")
time.Sleep(10) //等待10ns,但是效率低
}
常用办法:
package main
import (
"fmt"
"sync"
)
var Sy sync.WaitGroup
func hello(){
fmt.Println("Hello")
Sy.Done() //计数器-1
}
func main(){
Sy.Add(1) //计数器+1
go hello()
fmt.Println("Hello Main")
Sy.Wait() //等待计数器==0的时候直接退出
}
同时goroutine也可以使用匿名函数,但是再使用匿名函数的时候,容易产生闭包的问题,需要注意。
GOMAXPROCS设置使用CPU核心数
在Go1.5版本之前默认使用的是单核操作,在1.5版本后默认使用CPU全部核心进行操作,能够充分利用硬件资源。
//使用方法
runtine.GOMAXPROCS(核心数)
package main
import (
"fmt"
"sync"
"runtime"
)
var wg sync.WaitGroup
func hello(){
fmt.Println("Hello")
wg.Done()
}
func helloWorld(){
fmt.Println("HelloWorld")
wg.Done()
}
func main(){
runtime.GOMAXPROCS(4)
wg.Add(2) //计数器+2
go hello()
go helloWorld()
wg.Wait()
}
一个操作系统线程对应多个用户态goroutine
go语言程序可以同时使用多个操作系统线程
goroutine于OS线程是多对多的关系