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

两个常见的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{} // 阻塞
}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值