package main
import (
"fmt"
)
type worker struct {
channel chan int
done chan bool
}
func main() {
var workers [10]worker
for i:=0;i<10 ;i++ {
workers[i]=worker{
make(chan int),
make(chan bool),
}
go printNum(i,workers[i])
}
for i,w:=range workers {
w.channel<- 'a'+i
}
for i,w:=range workers {
w.channel<- 'A'+i
}
for _,w:=range workers {
<-w.done
<-w.done
}
//保障协程运行完毕,主协程main运行结束之后,其他协程也全部结束
//time.Sleep(time.Duration(time.Millisecond))
}
func printNum(i int,w worker){
for{
//io操作会进行调度
fmt.Println(i,"got num:",<-w.channel)
w.done<-true
}
}
在上面的程序中运行报错:
GOROOT=C:\Go #gosetup
GOPATH=E:\GoProgram\awsomeproject;E:\GoProgram\awsomeproject\src\video_server_1_5;E:\GoProgram;C:\Users\123\go #gosetup
C:\Go\bin\go.exe build -i -o C:\Users\123\AppData\Local\Temp\___go_build_testChannel_go.exe E:/GoProgram/awsomeproject/src/u2pppw/channel/testChannel.go #gosetup
"E:\goland\GoLand 2018.1.6\bin\runnerw.exe" C:\Users\123\AppData\Local\Temp\___go_build_testChannel_go.exe #gosetup
fatal error: all goroutines are asleep - deadlock!
0 got num: 97
1 got num: 98
2 got num: 99
3 got num: 100
4 got num: 101
5 got num: 102
6 got num: 103
7 got num: 104
8 got num: 105
9 got num: 106
goroutine 1 [chan send]:
main.main()
E:/GoProgram/awsomeproject/src/u2pppw/channel/testChannel.go:26 +0x1d1
goroutine 18 [chan send]:
main.printNum(0x0, 0xc042048060, 0xc0420480c0)
E:/GoProgram/awsomeproject/src/u2pppw/channel/testChannel.go:40 +0x11c
created by main.main
E:/GoProgram/awsomeproject/src/u2pppw/channel/testChannel.go:20 +0xf8
goroutine 19 [chan send]:
main.printNum(0x1, 0xc042048120, 0xc042048180)
E:/GoProgram/awsomeproject/src/u2pppw/channel/testChannel.go:40 +0x11c
created by main.main
E:/GoProgram/awsomeproject/src/u2pppw/channel/testChannel.go:20 +0xf8
goroutine 20 [chan send]:
main.printNum(0x2, 0xc0420481e0, 0xc042048240)
E:/GoProgram/awsomeproject/src/u2pppw/channel/testChannel.go:40 +0x11c
created by main.main
E:/GoProgram/awsomeproject/src/u2pppw/channel/testChannel.go:20 +0xf8
goroutine 21 [chan send]:
main.printNum(0x3, 0xc0420482a0, 0xc042048300)
E:/GoProgram/awsomeproject/src/u2pppw/channel/testChannel.go:40 +0x11c
created by main.main
E:/GoProgram/awsomeproject/src/u2pppw/channel/testChannel.go:20 +0xf8
goroutine 22 [chan send]:
main.printNum(0x4, 0xc042048360, 0xc0420483c0)
E:/GoProgram/awsomeproject/src/u2pppw/channel/testChannel.go:40 +0x11c
created by main.main
E:/GoProgram/awsomeproject/src/u2pppw/channel/testChannel.go:20 +0xf8
goroutine 23 [chan send]:
main.printNum(0x5, 0xc042048420, 0xc042048480)
E:/GoProgram/awsomeproject/src/u2pppw/channel/testChannel.go:40 +0x11c
created by main.main
E:/GoProgram/awsomeproject/src/u2pppw/channel/testChannel.go:20 +0xf8
goroutine 24 [chan send]:
main.printNum(0x6, 0xc0420484e0, 0xc042048540)
E:/GoProgram/awsomeproject/src/u2pppw/channel/testChannel.go:40 +0x11c
created by main.main
E:/GoProgram/awsomeproject/src/u2pppw/channel/testChannel.go:20 +0xf8
goroutine 25 [chan send]:
main.printNum(0x7, 0xc0420485a0, 0xc042048600)
E:/GoProgram/awsomeproject/src/u2pppw/channel/testChannel.go:40 +0x11c
created by main.main
E:/GoProgram/awsomeproject/src/u2pppw/channel/testChannel.go:20 +0xf8
goroutine 26 [chan send]:
main.printNum(0x8, 0xc042048660, 0xc0420486c0)
E:/GoProgram/awsomeproject/src/u2pppw/channel/testChannel.go:40 +0x11c
created by main.main
E:/GoProgram/awsomeproject/src/u2pppw/channel/testChannel.go:20 +0xf8
goroutine 27 [chan send]:
main.printNum(0x9, 0xc042048720, 0xc042048780)
E:/GoProgram/awsomeproject/src/u2pppw/channel/testChannel.go:40 +0x11c
created by main.main
E:/GoProgram/awsomeproject/src/u2pppw/channel/testChannel.go:20 +0xf8
Process finished with exit code 2
死锁问题,在第二个for循环执行完毕后,结构体实例中的信道channel都执行完了输入和输出的过程,而done信道只是执行了输入过程,输出(第四个for循环)还没有开始,此时再执行第三个for循环,向done信道内输入的话,造成死锁。可以在
func printNum(i int,w worker){
for{
//io操作会进行调度
fmt.Println(i,"got num:",<-w.channel)
w.done<-true
}
}
内新开协程:
func printNum(i int, w worker) {
for {
//io操作会进行调度
fmt.Println(i, "got num:", <-w.channel)
go func() { w.done <- true }()
}
}
输出结果:
5 got num: 102
1 got num: 98
4 got num: 101
0 got num: 97
3 got num: 100
0 got num: 65
1 got num: 66
7 got num: 104
8 got num: 105
2 got num: 99
9 got num: 106
2 got num: 67
5 got num: 70
6 got num: 103
4 got num: 69
7 got num: 72
6 got num: 71
8 got num: 73
3 got num: 68
9 got num: 74
或者在两个任务之间接收done信道内数据:
package main
import (
"fmt"
)
type worker struct {
channel chan int
done chan bool
}
func main() {
var workers [10]worker
for i := 0; i < 10; i++ {
workers[i] = worker{
make(chan int),
make(chan bool),
}
go printNum(i, workers[i])
}
for i, w := range workers {
w.channel <- 'a' + i
}
for _, w := range workers {
<-w.done
}
for i, w := range workers {
w.channel <- 'A' + i
}
for _, w := range workers {
<-w.done
}
//保障协程运行完毕,主协程main运行结束之后,其他协程也全部结束
//time.Sleep(time.Duration(time.Millisecond))
}
func printNum(i int, w worker) {
for {
//io操作会进行调度
fmt.Println(i, "got num:", <-w.channel)
w.done <- true
}
}
输出结果:
5 got num: 102
8 got num: 105
3 got num: 100
0 got num: 97
1 got num: 98
2 got num: 99
6 got num: 103
4 got num: 101
7 got num: 104
9 got num: 106
9 got num: 74
4 got num: 69
3 got num: 68
6 got num: 71
7 got num: 72
8 got num: 73
1 got num: 66
2 got num: 67
5 got num: 70
0 got num: 65
使用waitGroup:
package main
import (
"fmt"
"sync"
)
type worker struct {
channel chan int
wg *sync.WaitGroup
}
func main() {
var workers [10]worker
wg:=&sync.WaitGroup{}
wg.Add(20)
for i := 0; i < 10; i++ {
workers[i] = worker{
make(chan int),
wg,
}
go printNum(i, workers[i])
}
for i, w := range workers {
w.channel <- 'a' + i
}
for i, w := range workers {
w.channel <- 'A' + i
}
wg.Wait()
}
func printNum(i int, w worker) {
for in:=range w.channel{
fmt.Println(i, "got num:", in)
w.wg.Done()
}
}
输出结果:
8 got num: 105
0 got num: 97
0 got num: 65
3 got num: 100
1 got num: 98
1 got num: 66
4 got num: 101
6 got num: 103
7 got num: 104
5 got num: 102
9 got num: 106
2 got num: 99
2 got num: 67
9 got num: 74
7 got num: 72
6 got num: 71
4 got num: 69
3 got num: 68
8 got num: 73
5 got num: 70