Go语言核心36讲
郝林
《Go并发编程实战》作者,前轻松筹大数据负责人
立即订阅
24021 人已学习
课程目录
已完结 54 讲
0/4登录后,你可以任选4讲全文学习。
开篇词+学习路线 (3讲)
开篇词 | 跟着学,你也能成为Go语言高手
免费
预习篇 | 写给0基础入门的Go语言学习者
50 | 学习专栏的正确姿势
模块一:Go语言基础知识 (6讲)
01 | 工作区和GOPATH
02 | 命令源码文件
03 | 库源码文件
04 | 程序实体的那些事儿(上)
05 | 程序实体的那些事儿(中)
06 | 程序实体的那些事儿 (下)
模块二:Go语言进阶技术 (16讲)
07 | 数组和切片
08 | container包中的那些容器
09 | 字典的操作和约束
10 | 通道的基本操作
11 | 通道的高级玩法
12 | 使用函数的正确姿势
13 | 结构体及其方法的使用法门
14 | 接口类型的合理运用
15 | 关于指针的有限操作
16 | go语句及其执行规则(上)
17 | go语句及其执行规则(下)
18 | if语句、for语句和switch语句
19 | 错误处理(上)
20 | 错误处理 (下)
21 | panic函数、recover函数以及defer语句 (上)
22 | panic函数、recover函数以及defer语句(下)
模块三:Go语言实战与应用 (27讲)
23 | 测试的基本规则和流程 (上)
24 | 测试的基本规则和流程(下)
25 | 更多的测试手法
26 | sync.Mutex与sync.RWMutex
27 | 条件变量sync.Cond (上)
28 | 条件变量sync.Cond (下)
29 | 原子操作(上)
30 | 原子操作(下)
31 | sync.WaitGroup和sync.Once
32 | context.Context类型
33 | 临时对象池sync.Pool
34 | 并发安全字典sync.Map (上)
35 | 并发安全字典sync.Map (下)
36 | unicode与字符编码
37 | strings包与字符串操作
38 | bytes包与字节串操作(上)
39 | bytes包与字节串操作(下)
40 | io包中的接口和工具 (上)
41 | io包中的接口和工具 (下)
42 | bufio包中的数据类型 (上)
43 | bufio包中的数据类型(下)
44 | 使用os包中的API (上)
45 | 使用os包中的API (下)
46 | 访问网络服务
47 | 基于HTTP协议的网络服务
48 | 程序性能分析基础(上)
49 | 程序性能分析基础(下)
尾声与思考题答案 (2讲)
尾声 | 愿你披荆斩棘,所向无敌
新年彩蛋 | 完整版思考题答案
Go语言核心36讲
登录|注册

33 | 临时对象池sync.Pool

郝林 2018-10-26
到目前为止,我们已经一起学习了 Go 语言标准库中最重要的那几个同步工具,这包括非常经典的互斥锁、读写锁、条件变量和原子操作,以及 Go 语言特有的几个同步工具:
sync/atomic.Value
sync.Once
sync.WaitGroup
context.Context
今天,我们来讲 Go 语言标准库中的另一个同步工具:sync.Pool
sync.Pool类型可以被称为临时对象池,它的值可以被用来存储临时的对象。与 Go 语言的很多同步工具一样,sync.Pool类型也属于结构体类型,它的值在被真正使用之后,就不应该再被复制了。
这里的“临时对象”的意思是:不需要持久使用的某一类值。这类值对于程序来说可有可无,但如果有的话会明显更好。它们的创建和销毁可以在任何时候发生,并且完全不会影响到程序的功能。
同时,它们也应该是无需被区分的,其中的任何一个值都可以代替另一个。如果你的某类值完全满足上述条件,那么你就可以把它们存储到临时对象池中。
你可能已经想到了,我们可以把临时对象池当作针对某种数据的缓存来用。实际上,在我看来,临时对象池最主要的用途就在于此。
sync.Pool类型只有两个方法——PutGet。Put 用于在当前的池中存放临时对象,它接受一个interface{}类型的参数;而 Get 则被用于从当前的池中获取临时对象,它会返回一个interface{}类型的值。
取消
完成
0/1000字
划线
笔记
复制
© 版权归极客邦科技所有,未经许可不得传播售卖。 页面已增加防盗追踪,如有侵权极客邦将依法追究其法律责任。
该试读文章来自付费专栏《Go语言核心36讲》,如需阅读全部文章,
请订阅文章所属专栏。
立即订阅
登录 后留言

精选留言(13)

  • 到不了的塔
    临时对象池初始化时指定new字段对应的函数返回一个新建临时对象;
    临时对象使用完毕时调用临时对象池的put方法,把该临时对象put回临时对象池中。
    这样就能保证一个临时对象池中总有比较充足的临时对象。
    2018-11-17
    6
  • 闫飞
    这里存放的临时对象是否是无状态,无唯一标识符的纯值对象? 对象的类型是否都是一样,还是说必须要用户自己做好具体类型的判定?

    作者回复: 你放在一个池子里的实例最好是一个类型的,要不后面用的时候会很麻烦。

    2019-07-17
    1
  • 张sir
    还有一个问题,如果多goruntine同时申请临时对象池内资源,所有goruntine都可以同时获取到吗,还是只能有一个goruntine获取到,其它的goruntine都阻塞,直到这个goruntine释放完后才能使用

    作者回复: 我大概明白你的意思。这篇文章你可能还没有仔细看。

    你需要先搞清楚(以下内容在文章里都有):

    在涉及到本地池的 shared 字段的时候会有锁,但是这种锁是分段锁,也就是说,每个本地池都会有自己的锁。

    因此,在对应某个 P 的本地池的锁处于锁定状态的时候,所有正试图访问(不论是 Get 还是 Put)这个本地池的 goroutine 都会被阻塞。

    一个临时对象池拥有的本地池的数量与 P 的数量相同。所以,即使有 goroutine 因此被阻塞,往往也只是少数。又因为分段锁的缘故,它们被锁住的时间一般也是很短暂的。

    当你知道了这些,你就会明白,临时对象池在并发访问方面是很高效的。

    再结合我在专栏里揭示的访问步骤和细节,你应该就可以搞懂你问的问题了。

    2019-05-21
    1
  • 来碗绿豆汤
    是不是临时对象池里面最多有2p个临时对象
    2018-10-28
    1
  • 苏安
    老师,不知道还有几讲,最初的课程大纲有相关的拾遗章节,不知道后续的安排还有没?

    作者回复: 我会讲完的,放心,预计45讲左右。

    2018-10-26
    1
  • 虢国技匠
    二刷
    2019-11-29
  • 数字记忆
    这个代码很形象:

    package main

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

    // 一个[]byte的对象池,每个对象为一个[]byte
    var bytePool = sync.Pool{
    New: func() interface{} {
    b := make([]byte, 1024)
    return &b
    },
    }

    func main() {
    a := time.Now().Unix()
    fmt.Println(a)
    // 不使用对象池
    for i := 0; i < 1000000000; i++{
    obj := make([]byte,1024)
    _ = obj
    }
    b := time.Now().Unix()
    fmt.Println(b)
    // 使用对象池
    for i := 0; i < 1000000000; i++{
    obj := bytePool.Get().(*[]byte)
    _ = obj
    bytePool.Put(obj)
    }
    c := time.Now().Unix()
    fmt.Println(c)
    fmt.Println("without pool ", b - a, "s")
    fmt.Println("with pool ", c - b, "s")
    }

    // run时禁用掉编译器优化,才会体现出有pool的优势
    // go run -gcflags="-l -N" testSyncPool1.go
    2019-11-20
  • benying
    打卡,讲的蛮清楚了
    老师的课程难度比较适中,挺好的
    2019-06-13
  • 张sir
    你好,请问put一个不存在的临时对象池会引发别的问题吗

    作者回复: 你说的“不存在”是什么意思?

    2019-05-21
  • 我不会算法
    请教老师一个问题: Get方法从临时对象池中取走一个私有临时对象时, 会不会把自己的共享临时对象列表中的临时对象转移一个为私有临时对象, 以方便下一个Get方法调用? 从文中的内容看, 应该是不会的

    作者回复: Get 的时候只会想法设法拿到一个临时对象,而不会移动任何对象。

    2019-04-16
  • 虢国技匠
    打卡😘ོ
    2019-03-01
  • Supetsnail
    这个怎么做一下benchmark验证下效率?
    2018-11-25
  • Supetsnail
    这个怎么能做一个benchmark对比?
    2018-11-25
收起评论
13
返回
顶部