Go编程题:多协程顺次打印数字

458 阅读1分钟

1. 问题描述

  • 创建N个协程,每个协程负责打印一个数字,编程实现将所有数字顺次输出。
Input:
    N = 5
Output:
    1
    2
    3
    4
    5

2. 解决方案

2.1. 竞争方案

  • 通过竞争互斥锁实现
import (
	"fmt"
	"sync"
)

var N = 5

// 竞争型
func race() {
	// 当前执行到的序号
	curSeq := 1
	var mu sync.Mutex
	var wg sync.WaitGroup

	for i := 1; i <= N; i++ {
		// 将当前协程加入wg
		wg.Add(1)

		go func(id int) {
			for {
				// 尝试获取锁,并打印数据
				mu.Lock()
				if id == curSeq {
					fmt.Println(curSeq)
					curSeq += 1
					// 打印工作完成,解锁并跳出循环
					mu.Unlock()
					break
				}
				// 发现没到自己打印的时候,解锁,把机会留给别人
				mu.Unlock()
			}

			// 子协程工作完成,离开wg
			wg.Done()
		}(i)
	}

	// 主协程等待子协程完成
	wg.Wait()
}

2.2. 协同方案

  • 通过channel通信协同打印
import (
	"fmt"
	"sync"
)

var N = 5

func collaborate() {
	chans := make([]chan bool, N+1)
	for i := 0; i <= N; i++ {
		chans[i] = make(chan bool)
	}

	for i := 1; i <= N; i++ {
		go func(id int) {
			// 当前协程阻塞,直到收到前一个协程的信号
			<-chans[id-1]
			// 打印自己对应的序号
			fmt.Println(id)
			// 通知下一个协程干活
			chans[id] <- true
		}(i)
	}
	chans[0] <- true

	// 等待最后一个协程完成工作
	<-chans[N]
}