多go程通信(管道channel)
go 程通信
1、当涉及到多go程时,c 是使用互斥量,上锁来保持资源同步,避免资源竞争问题
2、go语言也支持这种方式,但go语言更好的解决方案是使用管道、通道channel
3、使用通道不需要我们去加锁
4、A往通道里写数据, B从通道中读数据,go自动帮我们做好了数据同步
用例:
package main import ( "fmt" ) func main() { // 创建管道 // 无缓冲通道 numChan := make(chan int) // 装数字的管道, 使用管道时一定要用make,同map一样,否则是nil // strChan := make(chan string) // 装字符串的管道 // 有缓冲通道 // numChan := make(chan int, 10)
go func() { for i := 0; i < 50; i++ { // 从管道中读出数据 res := <-numChan fmt.Printf("**** 读出 i: %v ****\n", res) } }() go func() { for i := 0; i < 20; i++ { // 向管道中写入数据 numChan <- i fmt.Printf("==子go程===>写入i: %d\n", i) // time.Sleep(1 * time.Second) } }() for i := 20; i < 50; i++ { // 向管道中写入数据 numChan <- i fmt.Printf("==主go程===>写入i: %d\n", i) // time.Sleep(1 * time.Second) } }
结论
1、当缓冲写满的时候,写阻塞;被读取后,再次恢复写。
2、当缓冲区读取完毕,读阻塞。
3、如果管道没有使用make分配空间,那么管道默认是nil的, 读取、写入都会阻塞。
4、对于一个管道,读与写的次数,必须对等。
通道读写对等
go通道使用时,要求我们读写一致,如果不一致会导致一下情况:
1、当读程序是在主进程进行时, 那么会导致程序崩溃
2、当读程序是在go程进行时, 那么会导致内存泄漏。(此时程序不会崩溃,但是会导致资源无法释放)
用例:
package main import ( "fmt" "time" ) func main() { // 有缓冲管道 nummChan := make(chan int, 10) // 写 go func() { for i := 0; i < 20; i++ { nummChan <- i fmt.Printf("子go程写: %v\n", i) } }() // 读:go程 go func() { for i := 0; i < 30; i++ { aa := <-nummChan fmt.Printf("主进程读: %v\n", aa) } }() // 读:主进程 // for i:=0; i<30;i++ { // aa := <- nummChan // fmt.Printf("主进程读: %v\n", aa) // } for { fmt.Printf("----> 主进程, 死循环\n") time.Sleep(1 * time.Second) } }
- 当执行主进程读时, 程序读取超出后会立即崩溃
- 当执行go程读时, 程序读取超出后会阻塞住(结论2)
for - range 变量管道
1、遍历管道时,只返回一个值
2、for range 是不知道管道是否已经写完,所以会一直在这里等待
3、在写入端,将管道关闭,for range 关闭的管道时,会自动退出
用例:
package main import ( "fmt" ) func main() {
numChan := make(chan int, 10) // 写 go func () { for i:=0; i<20; i++ { numChan <- i fmt.Printf("----> 子go程写入数据\n") } fmt.Printf("===== 写入完毕 =====") close(numChan) }() // 读 for i:= range numChan { fmt.Printf("--> 主进程读: %v\n", i) } }
总结:
- 当管道写满了,写阻塞。
- 当缓冲读完了,读阻塞。
- 如果管道没有使用make分配空间,管道默认是nil 值
- 从nil 的管道中读取数据、写入数据,都是阻塞(注意:不会崩溃)
- 从一个close的管道中读取数据,会返回零值(不会崩溃)
- 关闭一个已经close的管道,程序会崩溃
- 关闭管道的操作应该放在写入端
- 读、写次数一定要对等,否则:
- 在多个go程中,资源泄露
- 在主go程中,程序崩溃(报:deadlock!)