Concurrency
- 通过通信来共享而非通过共享来通信 并发模型采用 CSP communicating Seqyential process
- goroutine 运行在相同的地址空间
- 底层也是通过共享内存的加锁来实现 抽象级别层级更高
channel
-
channel 必须使用 make 创建并定义发送到 channel 的类型
-
cap 可以读取 channel 的缓存容量
-
ch:=make(chan int) // 定义同时规定发送到 chan 的类型 v:=1 ch<-v // 将 v 发送到 chan w:=<-ch // 从 ch中读取并赋值给 w
-
-
默认无缓存chan 接受和发送是阻塞的 除非另外一端准备好
-
value:<-c
读取会被阻塞 直到有数据接受 -
ch<-5
发送会被阻塞 直到有被读取 -
func sum(a []int, c chan int) { total:=0 for _,v:=range a{ total+=v } c<-total } func main() { a:=[...]int {1, 2, 3,4,5,6,7,8,9,0} c:=make(chan int) go sum(a[:len(a)/2],c) go sum(a[len(a)/2:],c) x,y:=<-c,<-c fmt.Println(x,y,x+y) }
-
-
Buffer channel 带缓存的 channel
-
ch:=make(chan type,cap)
在 cap 内的读写是无阻塞的 超过 cap 时候需要等待其他 goroutine 从 channel 中读取元素 释放空间 -
for i:=rang c
可以不断读取 channel 直到 channel 被显示关闭 -
close
关闭 channel 无法发送数据 但可以在消费方通过v,ok:=c;ok
断言来测试是否关闭 channel- 在生产者方关闭 channle 在消费者方容易产生 panic
- 结束 range 循环/无数据需要发送时候关闭 channel 才使用 close显式关闭
-
func fibonacc(n int, c chan int) { x,y:=1,1 for i:=0;i<n;i++ { c<-x x,y=y,x+y } close(c) // 显示关闭 channel } func main() { c:=make(chan int, 10) go fibonacc(cap(c),c) for i:=range c { fmt.Println(i) } }
-
-
多 channel 下 select
-
select 关键字监听 channel 上的数据流动
-
默认是阻塞的 只有监听的 channel 上数据流动才运行 多个 channel 准备好时select 随机选择执行
-
类似 switch 有
default
可设置超时来退出循环 -
func fibonacc(c, quit chan int) { x, y := 1, 1 for { select { // 类似 switch 监听 channel 上的数据流动 case c <- x: x, y = y, x+y case <-quit: fmt.Println("quit") return case <-time.After(5*time.Second) // 阻塞超过5 s情况 fmpl("timeOut") break; } } } func main() { c := make(chan int) quit:=make(chan int) go func() { for i := 0; i < 10; i++ { fmt.Println(<-c) } quit<-0 }() fibonacc(c,quit) }
channel 通信
func testAppendA(t *testing.T) { x := []int{1, 2, 3} appendA(x) fmt.Printf("main %v\n", x) } func appendA(x []int) { x[0] = 100 fmt.Printf("appendA %v\n", x) } func main() { ch := make(chan struct{}) go func() { for i := 1; i < 11; i++ { ch <- struct{}{} if i%2 == 1 { fmt.Println("奇数", i) } } }() go func() { for i := 0; i < 11; i++ { <-ch if i%2 == 0 { fmt.Println("偶数", i) } } }() time.Sleep(10 * time.Second) }
-
广播通信
func main() {
notify := make(chan struct{})
for i := 0; i < 10; i++ {
go func(i int) {
for {
select {
case <-notify:
fmt.Println("done...", i)
case <-time.After(1 * time.Second):
fmt.Println("wait notify", i)
}
}
}(i)
}
time.Sleep(1 * time.Second)
close(notify)
time.Sleep(3 * time.Second)
}
Goexit
- 退出当前 Goroutine 但defer 仍调用
Gosched
- 让出 goRoutine 权限
NumCPU
NumGoroutine
- 返回 cpu数目
- 返回执行和排队的任务总数
GOMAXPROCS
- 并行计算的 cpu 核数最大值 返回之前的核数值