Golang面试题: 3个goroutine交替打印ABC

开心一刻

       一位小帅哥和靓姑娘在火车上相遇。经过一阵“天南地北,生猛海鲜”之后,小帅哥拿出一副扑克与姑娘对玩:
  帅哥: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")
}
  1. 第一个for循环中为chanQueue数组中的每个channel实例化。同时给最后一个channel写一条数组,为了第一次输出能从第一个channel中输出,如果不写会造成死锁,而且需要创建一个协程来写,否则程序直接报错。
  2. 第二个for循环中lastChan意思是,如果当前chan要打印数据,必须是上一个chan打印完后才能打印。
  3. 在这里使用匿名函数的时候最好使用这种带参数的传参,而不是直接使用全局变量,否则因为协程并发执行的不确定性可能造成死锁。

文中都是我个人的理解,如有错误的地方欢迎下方评论告诉我,我及时更正,大家共同进步

  • 2
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值