Golang之Goroutinue专项篇

前言

主要分享协程相关的特点与基本用法

详情

名词普及

Goroutines

  • Go 中的并发执行单位,类似于轻量级的线程。
  • Goroutine 的调度由 Go 运行时管理,用户无需手动分配线程。
  • 使用 go 关键字启动 Goroutine。
  • Goroutine 是非阻塞的,可以高效地运行成千上万个 Goroutine

Channel

  • Go 中用于在 Goroutine 之间通信的机制
  • 支持同步和数据共享,避免了显式的锁机制
  • 使用 chan 关键字创建,通过 <- 操作符发送和接收数据。

Scheduler

Go 的调度器基于 GMP 模型,调度器会将 Goroutine 分配到系统线程中执行,并通过 M 和 P 的配合高效管理并发。

  • G:Goroutine
  • M:系统线程(Machine)
  • P:逻辑处理器(Processor)

示例

场景A:有N个任务等待消费,如何高性能的消费掉

import ("sync")
// 此处以切片代替任务
// 模拟任务投递
var task []string
for i:=0; i<100; i++ {
	task = append(task, fmt.Sprintf("%s-%d", "name", i))
}

// 任务消费
// 方案1:同步排队遍历消费
// 同步消费、效率低且阻塞
func consumerA(taskList []string) {
	for _, task := range taskList {
		fmt.Println(task)
	}
}

// 方案2,使用 Goroutinue,启用N个协程,把任务平均到每个协程中做处理
// 每个协程处理任务固定、可能浪费性能,原因:当某个协程中的任务阻塞或处理完时会挂起等待
func consumerC(taskList []string) {
	// 设置协程默认数
	defaultWorkers := 10
	var wg sync.WaitGroup
	chunkSize := (len(nameList) + defaultWorkerNum - 1) / defaultWorkerNum
	for i := 0; i < defaultWorkerNum; i++ {
		start := i * chunkSize
		end := start + chunkSize
		if end > len(nameList) {
			end = len(nameList)
		}
		wg.Add(1)
		go func(start, end int) {
			defer wg.Done()
			for _, name := range nameList[start:end] {
				fmt.Println(name)
			}
		}(start, end)
	}
	wg.Wait()
}


// 方案3,使用 Channel 
// 充分利用协程资源性能、当某个协程处理完时 任务进来会继续处理,不会等待,相比方案2 充分利用协程资源。
// 不会存在当某个协程处理任务阻塞或处理完一直等待的情况
func consumerC(taskList []string) {
	// 声明 task channel 通道、并追加任务
	taskChannel := make(chan string, len(taskList))
	
	// 设置协程默认数
	defaultWorkers := 10
	var wg sync.WaitGroup
	for i := 1; i <= defaultWorkers; i++ {
		wg.Add(1)
		go func () {
			defer wg.Done()
			for _, task := range taskChannel {
				fmt.Println(task)
			}
		}
	}
	for _, task := range taskList {
		taskChannel <- task
	}
	// 关闭channel
	close(taskChannel)
	// 等待Goroutinue
	wg.Wait()
}
  • 从以上三种方案来看方案三最为合适,合理利用空闲资源出现等待的情况较少
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值