文章目录
开心一刻
一位小帅哥和靓姑娘在火车上相遇。经过一阵“天南地北,生猛海鲜”之后,小帅哥拿出一副扑克与姑娘对玩:
帅哥:QQK?(谈谈看)
姑娘:Q45?(谈什么)
帅哥:Q21!(谈恋爱)
姑娘:8Q!!(不谈)
$%……!
快到站了,小帅哥不甘心,又拿出扑克:
帅哥:3QQK?(再谈谈看)
姑娘:948Q!!!(就是不谈)
帅哥:—%¥……)
题目介绍
使用3个goroutine交替打印ABC,并且在输出是也按照ABCABC输出
做法一
package main
import (
"fmt"
"sync"
)
func main() {
var ch1, ch2, ch3 = make(chan struct{}), make(chan struct{}), make(chan struct{})
var wg sync.WaitGroup
wg.Add(3)
go func(s string) {
defer wg.Done()
for i := 1; i <= 10; i++ {
<- ch1
fmt.Print(s)
ch2 <- struct{}{}
}
<- ch1
}("A")
go func(s string) {
defer wg.Done()
for i := 1; i <= 10; i++ {
<- ch2
fmt.Print(s)
ch3 <- struct{}{}
}
}("B")
go func(s string) {
defer wg.Done()
for i := 1; i <= 10; i++ {
<- ch3
fmt.Println(s)
ch1 <- struct{}{}
}
}("C")
ch1 <- struct{}{}
wg.Wait()
}
由同步channel控制线程之间的执行顺序即可。
题目扩展
使用N个协程交替打印英文字母
package main
import "fmt"
func main() {
chanNum := 4
chanQueue := make([]chan struct{}, chanNum)
var result = 0
exitChan := make(chan struct{})
for i := 0; i < chanNum; i++ {
chanQueue[i] = make(chan struct{})
if i == chanNum - 1 {
go func(i int) {
chanQueue[i] <- struct{}{}
}(i)
}
}
for i := 0; i < chanNum; i++ {
var lastChan, curChan chan struct{}
if i == 0 {
lastChan = chanQueue[chanNum - 1]
} else {
lastChan = chanQueue[i - 1]
}
curChan = chanQueue[i]
go func(i byte, lastChan, curChan chan struct{}) {
for {
if result > 20 {
exitChan <- struct{}{}
}
<- lastChan
fmt.Printf("%c\n", i)
result++
curChan <- struct{}{}
}
}('A'+byte(i), lastChan, curChan)
}
<- exitChan
fmt.Println("done")
}
- 第一个for循环中为chanQueue数组中的每个channel实例化。同时给最后一个channel写一条数组,为了第一次输出能从第一个channel中输出,如果不写会造成死锁,而且需要创建一个协程来写,否则程序直接报错。
- 第二个for循环中lastChan意思是,如果当前chan要打印数据,必须是上一个chan打印完后才能打印。
- 在这里使用匿名函数的时候最好使用这种带参数的传参,而不是直接使用全局变量,否则因为协程并发执行的不确定性可能造成死锁。
文中都是我个人的理解,如有错误的地方欢迎下方评论告诉我,我及时更正,大家共同进步