热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

Go学习_18_Golang的sync.Pool的对象池

Go学习_18_Golang的sync.Pool的对象池,Go语言社区,Golang程序员人脉社

Flutter、Golang、Python、编译原理、算法、Chrome原理学习系列文章抢先看请关注【码农帮派】

【Golang学习系列文章,请扫二维码】

上一节中我们通过Buffered channel实现了对象池的功能,但是我们发现在Golang的sync包中有一个Pool,sync.Pool其实是对象缓存机制。

sync.Pool的对象缓存是和Processor关联的。Processor在Golang的MPG中介绍过,M是Machine,一个M关联一个内核对象;P是协程处理器,是M运行的上下文环境;G就是协程。

对于Processor,它的数据对象如下图:

每个Processor包含一个私有对象和一个共享池,很多资料上将私有对象成为私有对象池,这是不合适的,因为它只能缓存一个对象,因此更为准确的应该是私有对象。

其中私有对象是协程安全的,共享池是协程不安全的。私有对象本身已经实现了锁,因此我们在访问私有对象的时候无需自己加锁,而共享池是协程不安全的,因此我们在使用共享池的时候是需要自己加锁的。

sync.Pool对象获取的流程:

  1. 尝试从私有对象获取

  2. 私有对象不存在,尝试从当前Processor的共享池中获取

  3. 如果当前Processor共享池也是空的,那么尝试从其他Processor的共享池中获取

  4. 如果所有子池都是空的,那么使用sync.Pool的New函数创建一个新的对象,并返回。

sync.Pool对象返回的流程:

  1. 如果私有对象不存在,则存储到私有对象中

  2. 如果私有对象已存在,则放入到当前Processor的共享池中

sync.Pool的使用方法:

pool := &sync.Pool {    New: func() interface{} {        return 0    },}
// 获取对象item := pool.Get().(int)
// 对象放回pool.Put(1)

在创建一个sync.Pool的时候,我们指定了一个New函数,保证在私有对象和每个共享池中获取不到对象的时候,可以进行对象初始化创建。

sync.Pool的生命周期

  • GC会清除sync.Pool缓存的数据对象

  • sync.Pool对象缓存的有效期为下一次GC之前

正是因为sync.Pool对象的周期会受到系统GC的影响,因此不能够被当作一种稳定的对象池来使用,只能当作对象缓存。

上面的代码中,我们首次从sync.Pool中获取对象,是通过New函数创建的,当我们使用放回函数放回一个缓存对象之后,再次获取,发现获取到的就是我们放回的对象数据。

我们在程序中手动出发一次GC:

从上面的结果可以看出,即使我们已经向sync.Pool中放回了对象,但是系统GC会将sync.Pool中的对象清空。

需要注意的是,我们首次从sync.Pool中获取对象是通过New函数创建的,我们需要将获取的对象放回到sync.Pool中,否则下次获取的时候,sync.Pool仍然是通过New函数重新创建并返回对象:

上面代码中,只有获取并没有放回,两次获取操作都触发了sync.Pool的New函数重新创建对象。

下面的代码中,我们在多协程中访问sync.Pool的对象,因为我们在协程中只获取,没有返回数据,所有后面协程获取的对象都是通过New函数创建的新对象:

sync.Pool总结:

  • sync.Pool适用于通过复用,来降低复杂对象的创建和GC的代价

  • sync.Pool协程安全的,内部实现了锁机制,会有锁的性能开销

  • sync.Pool中对象的生命周期受到GC的影响,不适合用作链接缓存池,也不适用于需要自己管理对象生命周期的对象池


推荐阅读
  • SQLite数据库CRUD操作实例分析与应用
    本文通过分析和实例演示了SQLite数据库中的CRUD(创建、读取、更新和删除)操作,详细介绍了如何在Java环境中使用Person实体类进行数据库操作。文章首先阐述了SQLite数据库的基本概念及其在移动应用开发中的重要性,然后通过具体的代码示例,逐步展示了如何实现对Person实体类的增删改查功能。此外,还讨论了常见错误及其解决方法,为开发者提供了实用的参考和指导。 ... [详细]
  • 第二十五天接口、多态
    1.java是面向对象的语言。设计模式:接口接口类是从java里衍生出来的,不是python原生支持的主要用于继承里多继承抽象类是python原生支持的主要用于继承里的单继承但是接 ... [详细]
  • 本文介绍了如何利用 `matplotlib` 库中的 `FuncAnimation` 类将 Python 中的动态图像保存为视频文件。通过详细解释 `FuncAnimation` 类的参数和方法,文章提供了多种实用技巧,帮助用户高效地生成高质量的动态图像视频。此外,还探讨了不同视频编码器的选择及其对输出文件质量的影响,为读者提供了全面的技术指导。 ... [详细]
  • Java Socket 关键参数详解与优化建议
    Java Socket 的 API 虽然被广泛使用,但其关键参数的用途却鲜为人知。本文详细解析了 Java Socket 中的重要参数,如 backlog 参数,它用于控制服务器等待连接请求的队列长度。此外,还探讨了其他参数如 SO_TIMEOUT、SO_REUSEADDR 等的配置方法及其对性能的影响,并提供了优化建议,帮助开发者提升网络通信的稳定性和效率。 ... [详细]
  • 使用Maven JAR插件将单个或多个文件及其依赖项合并为一个可引用的JAR包
    本文介绍了如何利用Maven中的maven-assembly-plugin插件将单个或多个Java文件及其依赖项打包成一个可引用的JAR文件。首先,需要创建一个新的Maven项目,并将待打包的Java文件复制到该项目中。通过配置maven-assembly-plugin,可以实现将所有文件及其依赖项合并为一个独立的JAR包,方便在其他项目中引用和使用。此外,该方法还支持自定义装配描述符,以满足不同场景下的需求。 ... [详细]
  • 本文深入探讨了Java多线程环境下的同步机制及其应用,重点介绍了`synchronized`关键字的使用方法和原理。`synchronized`关键字主要用于确保多个线程在访问共享资源时的互斥性和原子性。通过具体示例,如在一个类中使用`synchronized`修饰方法,展示了如何实现线程安全的代码块。此外,文章还讨论了`ReentrantLock`等其他同步工具的优缺点,并提供了实际应用场景中的最佳实践。 ... [详细]
  • 提升Android开发效率:Clean Code的最佳实践与应用
    在Android开发中,提高代码质量和开发效率是至关重要的。本文介绍了如何通过Clean Code的最佳实践来优化Android应用的开发流程。以SQLite数据库操作为例,详细探讨了如何编写高效、可维护的SQL查询语句,并将其结果封装为Java对象。通过遵循这些最佳实践,开发者可以显著提升代码的可读性和可维护性,从而加快开发速度并减少错误。 ... [详细]
  • 在过去,我曾使用过自建MySQL服务器中的MyISAM和InnoDB存储引擎(也曾尝试过Memory引擎)。今年初,我开始转向阿里云的关系型数据库服务,并深入研究了其高效的压缩存储引擎TokuDB。TokuDB在数据压缩和处理大规模数据集方面表现出色,显著提升了存储效率和查询性能。通过实际应用,我发现TokuDB不仅能够有效减少存储成本,还能显著提高数据处理速度,特别适用于高并发和大数据量的场景。 ... [详细]
  • Ihavetwomethodsofgeneratingmdistinctrandomnumbersintherange[0..n-1]我有两种方法在范围[0.n-1]中生 ... [详细]
  • 本文总结了一些开发中常见的问题及其解决方案,包括特性过滤器的使用、NuGet程序集版本冲突、线程存储、溢出检查、ThreadPool的最大线程数设置、Redis使用中的问题以及Task.Result和Task.GetAwaiter().GetResult()的区别。 ... [详细]
  • 在《Cocos2d-x学习笔记:基础概念解析与内存管理机制深入探讨》中,详细介绍了Cocos2d-x的基础概念,并深入分析了其内存管理机制。特别是针对Boost库引入的智能指针管理方法进行了详细的讲解,例如在处理鱼的运动过程中,可以通过编写自定义函数来动态计算角度变化,利用CallFunc回调机制实现高效的游戏逻辑控制。此外,文章还探讨了如何通过智能指针优化资源管理和避免内存泄漏,为开发者提供了实用的编程技巧和最佳实践。 ... [详细]
  • 工作8年后薪资从1万跃升至7万,网友惊叹:本科学历实属难得
    一位本科毕业生在工作8年后,凭借扎实的技术能力和不断的学习提升,成功将月薪从1万元提高到7万元,引发了网友们的广泛赞叹。这一成就不仅体现了个人的努力与坚持,也反映了当前技术领域对高素质人才的迫切需求。 ... [详细]
  • 本文介绍了如何利用 Delphi 中的 IdTCPServer 和 IdTCPClient 控件实现高效的文件传输。这些控件在默认情况下采用阻塞模式,并且服务器端已经集成了多线程处理,能够支持任意大小的文件传输,无需担心数据包大小的限制。与传统的 ClientSocket 相比,Indy 控件提供了更为简洁和可靠的解决方案,特别适用于开发高性能的网络文件传输应用程序。 ... [详细]
  • Java能否直接通过HTTP将字节流绕过HEAP写入SD卡? ... [详细]
  • 在Android应用开发中,实现与MySQL数据库的连接是一项重要的技术任务。本文详细介绍了Android连接MySQL数据库的操作流程和技术要点。首先,Android平台提供了SQLiteOpenHelper类作为数据库辅助工具,用于创建或打开数据库。开发者可以通过继承并扩展该类,实现对数据库的初始化和版本管理。此外,文章还探讨了使用第三方库如Retrofit或Volley进行网络请求,以及如何通过JSON格式交换数据,确保与MySQL服务器的高效通信。 ... [详细]
author-avatar
躺在地球上的熊
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有