当前位置: 首页 > 工具软件 > Fish Sync > 使用案例 >

Go 限制协程数、按顺序打印cat、dog、fish各100次

鲁涵映
2023-12-01

两个常见的Go测试题:

  1. 题1:如何限制协程个数?
  2. 题2:使用协程,按顺序打印cat、dog、fish各100次
package main

import (
	"fmt"
	"sync"
	"time"
)

/******************* 题1:限制协程个数 *******************/
// 任务函数
func job(i int, limitChan chan struct{}) {
	limitChan <- struct{}{}
	defer func() {
		<- limitChan
	}()

	time.Sleep(1 * time.Second)
	fmt.Printf("任务:%d已完成,当前协程数:%d\n", i, len(limitChan))
}

// limitChan限制协程数
func RunGoroutine() {
	limitChan := make(chan struct{}, 10) // 最大协程数限制为10个
	for i := 0; i < 100; i++ {
		go job(i, limitChan)
	}
}

/******************* 题2:按顺序打印cat、dog、fish各100次 *******************/
func PrintDog(dogChan chan struct{}, catChan, limitChan chan struct{}) {
	wgDCF.Add(1)
	<-dogChan
	// limitChan <- struct{}{} // 本来dogChan可以进入的,但是有可能因为limitChan满了,导致无法执行 <- dogChan,从而导致死锁

	defer func() {
		wgDCF.Done()
		// <-limitChan
	}()

	fmt.Println("Dog:", /*runtime.NumGoroutine(), len(limitChan)*/)
	catChan <- struct{}{}
}

func PrintCat(catChan chan struct{}, fishChan, limitChan chan struct{}) {
	wgDCF.Add(1)
	<-catChan
	// limitChan <- struct{}{}

	defer func() {
		wgDCF.Done()
		// <-limitChan
	}()

	fmt.Println("Cat:", /*runtime.NumGoroutine(), len(limitChan)*/)
	fishChan <- struct{}{}
}

func PrintFish(fishChan, catChan, limitChan chan struct{}) {
	wgDCF.Add(1)
	<-fishChan
	// limitChan <- struct{}{}

	defer func() {
		wgDCF.Done()
		// <-limitChan
	}()

	fmt.Println("Fish:", /*runtime.NumGoroutine(), len(limitChan)*/)
	catChan <- struct{}{}
}

var wgDCF sync.WaitGroup

func DCF() {
	limitChan := make(chan struct{}, 3) // 可省略:这里其实可以不加limitChan的,因为本身令牌就是按顺序传递的:dog->cat->fish,最多一个时刻就只能有一个limitChan
	dogChan := make(chan struct{}, 1)
	catChan := make(chan struct{}, 1)
	fishChan := make(chan struct{}, 1)

	defer func() {
		defer close(limitChan)
		defer close(dogChan)
		defer close(catChan)
		defer close(fishChan)
	}()

	dogChan <- struct{}{} // 先触发

	for i := 0; i < 100; i++ {
		go PrintDog(dogChan, catChan, limitChan)
		go PrintCat(catChan, fishChan, limitChan)
		go PrintFish(fishChan, dogChan, limitChan)
	}
	wgDCF.Wait()
	fmt.Println("---DCF end---")
}

func main() {
	// 1.限制协程数:
	// RunGoroutine()

	// 2.按顺序打印cat、dog、fish各100次
	DCF()

	for{} // 阻塞
}

 类似资料: