请完成goroutine和channel协同工作的案例,具体要求:
(1)开启一个writeData协程,向管道mtChan中写入50个整数.
(2)开启一个readData协程,从管道intChan中读取writeData写入的数据。
(3)注意:writeData和readDate操作的是同一个管道
(4)主线程需要等待writeData和readDate协程都完成工作才能退出(如果主线程不做处理,那么其他线程还没干完活就直接跑路了)
管道是引用类型,那么写入读取的都是同一个管道,也就是在不同函数不同栈里面读取的都是同一个管道。两个协程同时的向管道里面写入读取数据,而不是一个写完另外一个协程再去读取。
package main
import (
"fmt"
)
func writeData(initChan chan int) {
for i := 0; i <= 50; i++ {
//放入数据
initChan <- i
fmt.Println("write data:", i)
}
close(initChan)
}
func readData(initChan chan int, exitChan chan bool) {
//即使管道close之后并不影响读取,当在管道当中取不到数据才会退出
for {
//在从一个管道里面读取会返回两个值,ok是有没有正确读取到
v, ok := <-initChan
if !ok {
break
}
fmt.Println("read data:", v)
}
//readData任务完成之后
exitChan <- true
close(exitChan)
}
func main() {
//创建两个管道
initChan := make(chan int, 50)
exitChan := make(chan bool, 1)
go writeData(initChan)
go readData(initChan, exitChan)
for {
_, ok := <-exitChan
fmt.Println("ok=", ok)
if ok {
break
}
}
}
如果给的容量就是50,那么循环50次就刚好放进去了。如果管道和放进去的数据量不匹配,管道的容量小于放进去的数据,又不取出来,那么它就会阻塞,就会死锁。
这个管道可以容纳的数据量很小,要写的数据量很大,只要一边在写,另外一边在读是无所谓的。
如果写的快,读取的慢。那么在写的时候就会阻塞,编译器会发现虽然阻塞了,但是有另外一个协程在往里面读取数据,这样就不会发生死锁。
func producer(ch chan int) {
i := 0
for {
ch <- i
i++
}
}
func main() {
ch := make(chan int, 2)
go producer(ch)
for {
fmt.Println(<-ch)
time.Sleep(time.Second * 2)
}
}
0
1
2
3
4
5
6
7
进程 已完成,退出代码为 -1073741510 (0xC000013A: interrupted by Ctrl+C)
死锁编译器底层会分析,如果发现一个地方在不停的写,但是没有任何一个协程去读取这样就直接死锁,如果有一个协程在慢慢的读取这样不会死锁。和写入读取速度没有关系,但是必须有写入的协程和读取的协程。简而言之就是管道需要不停的流动。
标签:writeData,读取,写入,死锁,Golang,管道,协程 From: https://blog.51cto.com/u_14035463/9067685