sync包-Pool


cuishuangtodo

多图详解Go的sync.Pool源码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
// A Pool is a set of temporary objects that may be individually saved and
// retrieved.
//
// Any item stored in the Pool may be removed automatically at any time without
// notification. If the Pool holds the only reference when this happens, the
// item might be deallocated.
//
// A Pool is safe for use by multiple goroutines simultaneously.
//
// Pool's purpose is to cache allocated but unused items for later reuse,
// relieving pressure on the garbage collector. That is, it makes it easy to
// build efficient, thread-safe free lists. However, it is not suitable for all
// free lists.
//
// An appropriate use of a Pool is to manage a group of temporary items
// silently shared among and potentially reused by concurrent independent
// clients of a package. Pool provides a way to amortize allocation overhead
// across many clients.
//
// An example of good use of a Pool is in the fmt package, which maintains a
// dynamically-sized store of temporary output buffers. The store scales under
// load (when many goroutines are actively printing) and shrinks when
// quiescent.
//
// On the other hand, a free list maintained as part of a short-lived object is
// not a suitable use for a Pool, since the overhead does not amortize well in
// that scenario. It is more efficient to have such objects implement their own
// free list.
//
// A Pool must not be copied after first use.
type Pool struct {
noCopy noCopy

local unsafe.Pointer // local fixed-size per-P pool, actual type is [P]poolLocal
localSize uintptr // size of the local array

victim unsafe.Pointer // local from previous cycle
victimSize uintptr // size of victims array

// New optionally specifies a function to generate
// a value when Get would otherwise return nil.
// It may not be changed concurrently with calls to Get.
New func() interface{}
}

sync.Pool的实现,懒汉模式还是饿汉模式?

sync.Pool 的实现是懒汉模式,在 Go 程序启动时并不会创建任何对象,而是等到需要用到对象时再去创建。这与饿汉模式的主要区别在于,饿汉模式在程序启动时就会创建对象实例。

sync.Pool 通过一个可选的 New 函数提供了一个创建新对象的方法。如果 Pool 中没有可重用的对象,则 New 函数将被调用来创建一个新的对象实例。Pool 可以安全地被多线程使用,并且在实际应用中往往能够有效地减少内存分配和垃圾回收次数,提高程序的性能表现。

需要注意的是,sync.Pool 并不是一个线程安全的数据结构,它的实现依赖于 Go 语言的协程调度机制来保证多线程访问的正确性。在使用 sync.Pool 时,需要仔细考虑对象的生命周期和并发访问的情况,以避免出现意外的问题。


是不是并发安全的?


sync.Pool 是 Go 标准库中提供的对象池实现,它可以用于减少内存分配和垃圾回收的负担,提高程序性能。在多线程并发的场景下,sync.Pool 的使用是安全的。

sync.Pool 在底层会维护一个池子,其中存放了一些可重用的对象。当需要获取对象时,sync.Pool 会优先从池子中获取可用的对象,如果没有可用对象,就调用 New 方法来创建一个新的对象。获取完对象后,需要对对象进行处理之后才能还给池子。

由于 sync.Pool 内部已经实现了对对象数量、池子容量等方面的管理,因此使用 sync.Pool 可以很好地避免了一些常见的并发问题,例如死锁、竞态条件等。另外,sync.Pool 本身也是线程安全的,可以在多个协程中并发地使用。

需要注意的是,在使用 sync.Pool 时,需要仔细考虑对象的生命周期和并发访问的情况。如果对象不是线程安全的,那么在使用过程中可能会引发并发问题。另外还需要注意对象的状态,避免出现不同协程之间对同一个对象进行修改的情况,进而引发竞态条件。


源码中或知名项目中的使用


https://www.cnblogs.com/qcrao-2018/p/12736031.html




源码分析:

深度解密Go语言之sync.pool

Go sync.Pool 浅析

理解Go 1.13中sync.Pool的设计与实现

Go 1.13中 sync.Pool 是如何优化的?