信道channel 概念
一个可以阻塞程序运行的队列,使用于并发状态下的消息传递
信道阻塞总结
-
同步信道(队列大小为0,接发消息立即阻塞)
-
接收数和发送数不相等
func err1() { c := make(chan int) c <- 0 } func err2() { c := make(chan int) <-c }
-
在同一线程接收和发送于同一个同步信道
func err3() { c := make(chan int) c <- 0 // 在这一步线程被阻塞了,无法执行到下一步 <-c }
-
-
异步信道 (有缓冲区)
-
发送数超过缓冲大小会阻塞
func err4() { c := make(chan int, 1) c <- 0 c <- 0 <-c <-c }
-
接收数大于发送数阻塞
func err5() { c := make(chan int, 1) <-c }
-
发送数大于接受数,但多的部分小于缓冲区容量不阻塞
func ok1() { c := make(chan int, 1) c <- 0 }
-
-
关闭的信道
-
再发送或关闭会panic
func err6() { ch := make(chan int) close(ch) close(ch) } func err7() { ch := make(chan int) close(ch) ch <- 0 }
-
再读取
func test3() { ch := make(chan int, 1) ch <- 3 a := 1 close(ch) a, ok := <-ch fmt.Println(a, ok) } //3 true func test2() { ch := make(chan int) close(ch) var a = 1 a, ok := <-ch fmt.Println(a, ok) } //0 false
-
-
其他情况
-
在子线程产生死锁,但主线程不同步,程序依然会退出
func main() { go err1() }
-
channel 遍历
+ 两种遍历方式
不确定信道长度的话,发送完最好关闭信道
~~~go
func loop(c chan int) {
for i := 1; i < 10; i++ {
c <- i
}
for i := 1; i < 1e8; i++ {
i = i + i - i
}
c <- 10
close(c)
}
func forchan(proc func(chan int)) {
var c = make(chan int)
go proc(c)
for k := range c {
fmt.Printf("%d ", k)
}
fmt.Println()
}
func whilechan(proc func(chan int)) {
var c = make(chan int)
go proc(c)
for {
if d, ok := <-c; ok {
fmt.Printf("%d ", d)
} else {
break
}
}
fmt.Println()
}
func main() {
forchan(loop)
whilechan(loop)
}
~~~
+ 遍历不清楚长度的channel,如果不close的化会造成死锁
多信道选择 for-select
语法很简单看书,实现机制不清楚,会不会产生死锁后议
网友评论