gopool 源码分析

gopool

gopool是字节跳动开源节流的gopkg包中协程池的一个实现。

关键结构

协程池:

type pool struct {// The name of the poolname string// capacity of the pool, the maximum number of goroutines that are actually working// 协程池的最大容量cap int32// Configuration informationconfig *Config// linked list of tasks// 任务链表taskHead  *tasktaskTail  *tasktaskLock  sync.MutextaskCount int32// Record the number of running workers// 运行中的协程数workerCount int32// This method will be called when the worker panic// 出现 panic 时调用、 panicHandler func(context.Context, interface{})
}

任务:

type task struct {ctx context.Contextf   func()next *task
}

worker:

type worker struct {pool *pool
}

源码分析

先说一下 gopool 的工作流程:

  1. 通过 Go 或者 CtxGo 方法调用
  2. 从 taskPool 中取出一个 t
  3. 如果当前的积压task达到阈值且worker(工作协程)的数量未达到上限,则新建一个worker。

pool.cap 最大工作协程与实际运行的最大协程可能会存在误差。因为新建worker这块不是原子操作:

if (atomic.LoadInt32(&p.taskCount) >= p.config.ScaleThreshold && p.WorkerCount() < atomic.LoadInt32(&p.cap)) || p.WorkerCount() == 0 {// 工作协程加1p.incWorkerCount()w := workerPool.Get().(*worker)w.pool = pw.run()}

worker 的最大数量不会超过pool.cap 。worker run 流程比较简单:

  1. 循环的从 pool 中取出 task 执行

为了方便查看源码,我把相关代码都粘到了下面的,详细流程如下:

var workerPool sync.Poolvar taskPool sync.Pool// 初始化 taskPool
func init() {taskPool.New = newTask
}func (p *pool) Go(f func()) {p.CtxGo(context.Background(), f)
}func (p *pool) CtxGo(ctx context.Context, f func()) {// 从 taskPool 中取 task,避免频繁创建销毁t := taskPool.Get().(*task)t.ctx = ctx// 赋值执行函数t.f = f// 将 t 添加到任务链表里,加锁保证并发安全p.taskLock.Lock()if p.taskHead == nil {p.taskHead = tp.taskTail = t} else {p.taskTail.next = tp.taskTail = t}p.taskLock.Unlock()// 任务链表数量原子加 1atomic.AddInt32(&p.taskCount, 1)// The following two conditions are met:// 1. the number of tasks is greater than the threshold.// 2. The current number of workers is less than the upper limit p.cap.// or there are currently no workers.// 满足以下两个条件:// 1.任务数大于等于设置的阈值(默认为1)// 2.当前的协程数低于上限,或者目前没有工人if (atomic.LoadInt32(&p.taskCount) >= p.config.ScaleThreshold && p.WorkerCount() < atomic.LoadInt32(&p.cap)) || p.WorkerCount() == 0 {// 工作协程加1p.incWorkerCount()w := workerPool.Get().(*worker)w.pool = pw.run()}
}func (w *worker) run() {go func() {for {var t *taskw.pool.taskLock.Lock()if w.pool.taskHead != nil {// 取出任务t = w.pool.taskHeadw.pool.taskHead = w.pool.taskHead.nextatomic.AddInt32(&w.pool.taskCount, -1)}// 没有任务则结束if t == nil {// if there's no task to do, exitw.close()w.pool.taskLock.Unlock()w.Recycle()return}w.pool.taskLock.Unlock()func() {defer func() {if r := recover(); r != nil {if w.pool.panicHandler != nil {w.pool.panicHandler(t.ctx, r)} else {msg := fmt.Sprintf("GOPOOL: panic in pool: %s: %v: %s", w.pool.name, r, debug.Stack())logger.CtxErrorf(t.ctx, msg)}}}()// 执行t.f()}()t.Recycle()}}()
}func (t *task) Recycle() {t.zero()taskPool.Put(t)
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.pswp.cn/web/82922.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【工作记录】接口功能测试总结

如何对1个接口进行接口测试 一、单接口功能测试 1、接口文档信息 理解接口文档的内容&#xff1a; 请求URL: https://[ip]:[port]/xxxserviceValidation 请求方法: POST 请求参数: serviceCode(必填), servicePsw(必填) 响应参数: status, token 2、编写测试用例 2.1 正…

Linux中su与sudo命令的区别:权限管理的关键差异解析

&#x1f49d;&#x1f49d;&#x1f49d;欢迎莅临我的博客&#xff0c;很高兴能够在这里和您见面&#xff01;希望您在这里可以感受到一份轻松愉快的氛围&#xff0c;不仅可以获得有趣的内容和知识&#xff0c;也可以畅所欲言、分享您的想法和见解。 推荐&#xff1a;「storms…

乐观锁与悲观锁的实现和应用

乐观锁与悲观锁&#xff1a;原理、实现与应用详解 在并发编程和数据库操作中&#xff0c;乐观锁和悲观锁是两种重要的并发控制策略&#xff0c;它们在原理、实现方式和应用场景上存在显著差异。下面我们将通过图文结合的方式&#xff0c;深入探讨这两种锁机制。 一、基本概念 1…

ios苹果系统,js 滑动屏幕、锚定无效

现象&#xff1a;window.addEventListener监听touch无效&#xff0c;划不动屏幕&#xff0c;但是代码逻辑都有执行到。 scrollIntoView也无效。 原因&#xff1a;这是因为 iOS 的触摸事件处理机制和 touch-action: none 的设置有关。ios有太多得交互动作&#xff0c;从而会影响…

Redis主从复制原理二 之 主从复制工作流程

概述 本文紧接「Redis主从复制的原理一 之 概述」&#xff0c;详细介绍了Redis的主从服务过程及原理。 主从复制工作流程 主从复制过程大体可以分为3个阶段&#xff1a; 建立连接阶段&#xff08;即准备阶段&#xff09;数据同步阶段命令传播阶段 阶段一&#xff1a;建立连接阶…

Markdown基础(1.2w字)

1. Markdown基础 这次就没目录了&#xff0c;因为md格式太乱了写示例&#xff0c;展示那些都太乱了&#xff0c;导致目录很乱。 &#xff08;我是XX&#xff0c;出现了很多错误&#xff0c;有错误和我说&#xff09; 1.1 Markdown简介 Markdown是一种轻量级的标记语言&#…

JAVA-springboot log日志

SpringBoot从入门到精通-第8章 日志的操作 一、Spring Boot默认的日志框架 SpringBoot支持很多种日志框架&#xff0c;通常情况下&#xff0c;这些日志框架都是由一个日志抽象层和一个日志实现层搭建而成的&#xff0c;日志抽象层是为记录日志提供的一套标准且规范的框架&…

Vue 渲染 Markdown 文件完全指南

前言 大家好&#xff0c;我是一诺&#xff0c;今天分享的是vue中渲染markdown文件。这是一个常见的需求&#xff0c;比如用户隐私协议页、技术说明等文档页面~ 本文将详细介绍如何在 Vue 中渲染 Markdown 文件&#xff0c;并美化代码块的显示效果。 基础概念 什么是 Markdo…

Science Robotics:UCLA 贺曦敏团队综述自主软体机器人

在机器人中实现类似生命的自主性一直是研究的方向&#xff0c;但目前大多数软体机器人仍依赖外部刺激操控来产生持续运动。为了实现能够自我调节感知 、 决策和驱动的自主物理智能&#xff08;autonomous physical intelligence&#xff0c;API&#xff09;&#xff0c;一种有前…

基于LangChain构建高效RAG问答系统:向量检索与LLM集成实战

基于LangChain构建高效RAG问答系统&#xff1a;向量检索与LLM集成实战 在本文中&#xff0c;我将详细介绍如何使用LangChain框架构建一个完整的RAG&#xff08;检索增强生成&#xff09;问答系统。通过向量检索获取相关上下文&#xff0c;并结合大语言模型&#xff0c;我们能够…

【Java学习笔记】SringBuffer类(重点)

StringBuffer&#xff08;重点&#xff09; 1. 基本介绍 &#xff08;1&#xff09;StringBuffer是可变的字符序列&#xff0c;可以对字符串内容惊醒增删 &#xff08;2&#xff09;很多方法喝String相同&#xff0c;但StringBuffer可变长度 &#xff08;3&#xff09;Strin…

计算机网络领域所有CCF-A/B/C类期刊汇总!

本期小编统计了【计算机网络】领域CCF推荐所有期刊的最新影响因子&#xff0c;分区、年发文量以及投稿经验&#xff0c;供大家参考&#xff01; CCF-A类 1 IEEE Journal on Selected Areas in Communications 【影响因子】13.8 【期刊分区】JCR1区&#xff0c;中科院1区TOP …

AI-Sphere-Butler之如何启动AI全能管家教程(WSL测试环境下适用)

环境&#xff1a; Ubuntu20.04 WSL2 问题描述&#xff1a; AI-Sphere-Butler之如何启动AI全能管家教程(WSL测试环境下适用) 解决方案&#xff1a; 打开管家大模型 1.运行大模型在cmd下输入&#xff1a; ollama run qwen2.5-3bnsfwny运行管家 数字人运行脚本&#xff…

【python深度学习】Day 47 注意力热图可视化

知识点&#xff1a;热力图 作业&#xff1a;对比不同卷积层热图可视化的结果 一、概念 为了方便观察输出&#xff0c;将特征图进行可视化。特征图本质就是不同的卷积核的输出&#xff0c;浅层指的是离输入图近的卷积层&#xff0c;浅层卷积层的特征图通常较大&#xff0c;而深层…

C#语音识别:使用Whisper.net实现语音识别

C#语音识别&#xff1a;使用Whisper.net实现语音识别 在当今数字化时代&#xff0c;语音识别技术已广泛应用于智能助手、语音转文字、会议记录等众多领域。对于 C# 开发者而言&#xff0c;如何快速、高效地实现语音识别功能呢&#xff1f;今天&#xff0c;我们就来介绍一个强大…

开源分享|适合初创商家的餐饮系统,基于thinkphp8+element-plus

一、项目介绍 三勾餐饮点餐连锁版系统是一个基于thinkphp8element-plusuniapp打造的面向开发的小程序商城的全面解决方案&#xff0c;旨在为连锁餐饮企业提供高效的点餐与管理服务。该系统支持多端应用发布&#xff0c;包括微信小程序、H5、安卓及iOS平台&#xff0c;实现数据…

rec_pphgnetv2完整代码学习(一)

rec_pphgnetv2是paddleocr_v5中的重要改进&#xff0c;因此对其完整代码进行学习十分之有必要。 一、IdentityBasedConv1x1 这段代码定义了 IdentityBasedConv1x1 类&#xff0c;它是 PaddleOCRv5 中 rec_pphgnetv2 模型的关键改进之一。该层通过将恒等映射&#xff08;Ident…

vue3+dify从零手撸AI对话系统

vue3dify从零手撸AI对话系统 前言 近年来&#xff0c;人工智能技术呈现爆发式增长&#xff0c;其应用已深度渗透至各行各业。甚至家里长辈们也开始借助AI工具解决日常问题。作为程序员群体&#xff0c;我们更应保持技术敏锐度&#xff0c;紧跟这波浪潮。 回溯求学时期&#xf…

robot_lab train的整体逻辑

Go2机器人推理(Play)流程详细分析 概述 本文档详细分析了使用命令 python scripts/rsl_rl/base/play.py --task RobotLab-Isaac-Velocity-Rough-Unitree-Go2-v0 进行Go2机器人推理的完整流程&#xff0c;基于实际的代码实现&#xff0c;包括模型加载、环境配置调整、推理循环…

Python Day45

Task&#xff1a; 1.tensorboard的发展历史和原理 2.tensorboard的常见操作 3.tensorboard在cifar上的实战&#xff1a;MLP和CNN模型 效果展示如下&#xff0c;很适合拿去组会汇报撑页数&#xff1a; 作业&#xff1a;对resnet18在cifar10上采用微调策略下&#xff0c;用tens…