golang 面试题,多个协程轮流、依次、按顺序,输出数字

题目解释

用go实现一个多协程打印数字的功能,要求每个协程之间轮流、依次、按顺序交替打印数字。

举例:2个协程,依次轮流按顺序打印数字10,协程m1打印数字1,协程m2打印数字2,接着协程m1打印数字3,协程m2打印数字4,以此类推

m1:1
m2:2
m1:3
m2:4
m1:5
m2:6
...

给定协程数M,和要打印的数字范围N,保证所有的goroutine是按顺序执行,执行完之后所有协程正常退出。

实现

有序的实现,参考链表的结构,串起来依次执行,所以我定义了一个结构

type ListChan struct {
	ch   chan int
	id   string
	next *ListChan
	wg   *sync.WaitGroup
}

完整的实现如下:


import (
	"fmt"
	"sync"
)

type ListChan struct {
	ch   chan int
	id   string
	next *ListChan
	wg   *sync.WaitGroup
}

// Print 用于输出的方法
func (l *ListChan) Print(N int, finish chan struct{}) {
	go func() {
		defer l.wg.Done()
		for {
			select {
			case num := <-l.ch:
				if num > N {
					finish <- struct{}{}
					return
				}

				fmt.Printf("%s: %d\n", l.id, num)
				l.next.ch <- num + 1

			case <-finish:
				finish <- struct{}{}
				return
			}
		}
	}()
}

// 用于构建和运行多个顺序实例的方式
func Create(M, N int) {
	ls := make([]*ListChan, M)

	wg := sync.WaitGroup{}
	finish := make(chan struct{}, M)

	for i := 0; i < M; i++ {
		ls[i] = &ListChan{
			ch: make(chan int),
			id: fmt.Sprintf("m%d", i+1),
			wg: &wg,
		}
	}

	for i := 0; i < M; i++ {
		if i == M-1 {
			ls[i].next = ls[0]
		} else {
			ls[i].next = ls[i+1]
		}
		wg.Add(1)
		ls[i].Print(N, finish)
	}
	ls[0].ch <- 1

	wg.Wait()
	for i := 0; i < M; i++ {
		close(ls[i].ch)
	}
	close(finish)
}

func main() {
	Create(2, 10)
}

执行完成后退出的方式不够优雅,采用了一个用于发送停止指令的有缓存chan,本想在数量超过N时,通过close(l.next.ch)来循环关闭,可这种方式非常容易死锁,有没有更优雅的退出方式呀?评论里留下你的答案吧

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值