goroutine编程题

题目

创建10个goroutine,id分别是0,1,2,3...9

每个goroutine只能打印最后一位是自己id号的数字, 例如: 3号只能打印3, 13, 23, 33...

编写一个程序,依次打印1-10000

第一想法是全局锁,如果只用一个锁,那就是10个goroutine一起抢锁,10个协程加10个锁的话,还要交替解锁。所以选择用channel,goroutine交替向下个管道发送消息。

读取空的channel会根据channel类型返回空的数据,所以需要判断channel读取是否成功,i, ok <- c,判断ok的值

我的解答

解析题目,10个goroutine,但是需要依次打印1-10000,

import (
"fmt"
"time"
)


var IsRunning = true

func print(gid int, m map[int]chan int) {
curChan := m[gid]
nextChan := m[(gid+1)%10]
for IsRunning {
select {
case i, ok := <-curChan:
if ok {
fmt.Println(fmt.Sprintf("%d goroutine id=%d", i, gid))
i++
if i > 10000 {
IsRunning = false
} else {
nextChan <- i
}
}
}
}

}

func printInOrder() {

memo := map[int]chan int{}
for i := 0; i < 10; i++ {
c := make(chan int, 1)
memo[i] = c
}
fmt.Printf("%#+v\n", memo)

for i := 0; i < 10; i++ {
go print(i, memo)
}
firstChan := memo[0]
firstChan <- 0
for IsRunning {
// time.Sleep(time.Millisecond)
}
defer func() {
for k, c := range memo {
fmt.Printf("关闭: %d\n", k)
close(c)
}
}()
}

func main() {
start := time.Now()
printInOrder()
fmt.Printf("用时: %s", time.Since(start))
}
# 输出:
9976 goroutine id=6
9977 goroutine id=7
9978 goroutine id=8
9979 goroutine id=9
9980 goroutine id=0
9981 goroutine id=1
9982 goroutine id=2
9983 goroutine id=3
9984 goroutine id=4
9985 goroutine id=5
9986 goroutine id=6
9987 goroutine id=7
9988 goroutine id=8
9989 goroutine id=9
9990 goroutine id=0
9991 goroutine id=1
9992 goroutine id=2
9993 goroutine id=3
9994 goroutine id=4
9995 goroutine id=5
9996 goroutine id=6
9997 goroutine id=7
9998 goroutine id=8
9999 goroutine id=9
10000 goroutine id=0
用时: 392.8411ms