首先并行!=并发,并发是逻辑上的并行.
例如:多个程序在单核处理器上运行,每个程序只能在对应的时间片上运行,因为时间片很短,看起来就像是并行.
一.go语言级别的线程goroutine
goroutine是Go语言中的轻量级线程实现.它是一个普通的函数,只需使用保留字 go 作为开头。
例如:两个goroutine打印1-10
//这个程序是不会输出的,因为go还没执行完成,main已经退出了
func test(){
for i:=0; i<10 ;i++{
fmt.Print(i)
}
}
func main() {
go test()
go test()
}
解决上面的问题可以让main等待一段时间,让test执行完成,也可以使用信道进行通信.
1)在main的最后加上time.Sleep(time.Second)
停顿一秒
2)使用信道:channel
func test(){
for i:=0; i<10 ;i++{
fmt.Print(i)
}
ch<-0
}
func main() {
go test()
go test()
<-ch
<-ch
}
对于channel类似于linux中的管道,信道可以分为无缓冲的和有缓冲的.对于无缓冲的放了数据就需要取出,否则阻塞;对于有缓冲的信道,可以存储对应大小的数据,满了以后就在存数据就类似于非阻塞的,会发生阻塞.
eg: ch := make(chan type, value)
二.go中的并行
对于上面的例子,输出结果跟串行结果一样,why??
因为Go默认所有的goroutine只能在一个线程里(单核)跑.而一个goroutine不阻塞是不会把CPU让让给其他goroutine的.所以执行结果类似于串行.
对于Go中的并行可以使用runtime包中的函数:
func test(){
for i:=0; i<10 ;i++{
fmt.Print(i)
}
ch<-0
}
func main() {
//使用两个核
runtime.GOMAXPROCS(2)
go test()
go test()
<-ch
<-ch
}
上面会抢占式输出
在多核情况下,如果一个goroutine发生阻塞,其他goroutine会在另一个线程(核)上执行