go协程实例-2

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

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值