并行是程序在任一时刻都同时运行,并发是单位时间内同时运行,实际微观上是有先后的。
通过go关键字来调用一个goroutine,go关键字后面必须跟一个函数,不能是语句或其他东西,函数返回值忽略
package main
import (
"runtime"
"time"
)
func main() {
go func(){
sum := 0
for i := 0; i<10000; i++{
sum += i
}
println(sum)
time.Sleep(2*time.Second)
}() //不要忘记最后的括号
//相当于
sum = func{
sum := 0
for i := 0; i<10000; i++{
sum += i
}
println(sum)
time.Sleep(2*time.Second)
}
go sum()
//runtime.NumGoroutine()显示当前goroutine数目
println("NumGoroutine = ", runtime.NumGoroutine())
time.Sleep(5*time.Second)
//这边是为了方式main routine提前完成,而此时sum runtine还没完成
//所以拖了点时间
}
package main
import (
"runtime"
"time"
)
func sum(){
sum :=0
for i:=0; i<10000; i++{
sum += i
}
println(sum)
time.Sleep(1*time.Second)
}
func main() {
go sum()
println("NumGoroutine = ", runtime.NumGoroutine())
time.Sleep(5*time.Second)
}
1.go执行是非阻塞的,不会等待
2.go后面的函数返回值会被忽略
3.调度器不能保证多个goroutine执行次序
go func(){
println(1)
}()
go func(){
println(2)
}()
go func(){
println(3)
}()
//顺序不一定
4.所有goroutine都是平等调度
5.go会为main函数创建一个goroutine
chan 即channel,通道是goroutine之间通信和同步的重要组件。在go里面不是通过共享内存来通信,而是通过通信来共享内存。
通道是一个类型,用chan来声明,但简单声明var a chan int 没有实际意义,其值是nil。go中用make来创建通道
//创建一个无缓冲的通道,通道存放元素的类型为datatype
make(chan datatype)
//创建一个有10个缓冲的通道,通道存放元素的类型为datatype
make(chan datatype, 10)
通道分为有缓冲和无缓冲的,内置cap,len函数。无缓冲cap,len都是0, 有缓冲,cap是容量,len是没有被读取的元素数。无缓冲的通道既可以用于通信,也可以用于两个goroutine同步,有缓冲的通道主要用于通信。
func main() {
c := make(chan struct{})
ci := make(chan int , 100)
go func (i chan struct{}, j chan int) {
for i:=0; i<10; i++{
ci <- i
}
close(ci) //将ci通道关闭
c <-struct{}{}
}(c, ci)
println("NumGoroutine=", runtime.NumGoroutine())
<-c //读通道c,通过通道进行同步等待
//但是我这边还是numgoroutine还是2
//需要用sleep5snum变为1
//time.Sleep(5*time.Second)
println("NumGoroutine=", runtime.NumGoroutine())
for v := range ci{
println(v)
}
}