前面我们已经陆续介绍了 sync 包提供的各种同步工具,比如互斥锁、条件变量、原子操作、多协程协作等,今天我们来看另外一种工具。
在高并发场景下,我们会遇到很多问题,垃圾回收(GC)就是其中之一。Go 语言中的垃圾回收是自动执行的,这有利有弊,好处是避免了程序员手动对垃圾进行回收,简化了代码编写和维护,坏处是垃圾回收的时机无处不在,这在无形之中增加了系统运行时开销。在对系统性能要求较高的高并发场景下,这是我们应该主动去避免的,因此这需要对对象进行重复利用,以避免产生太多垃圾,而这也就引入了我们今天要讨论的主题 —— sync 包提供的 Pool 类型:
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
// 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{}
}
PutGetsync.PoolPutinterface{}Getinterface{}GetGetNewNewGetnil
下面我们来看个简单的示例代码:
package main
import (
"fmt"
"sync"
)
func main() {
var pool = &sync.Pool{
New: func() interface{} {
return "Hello,World!"
},
}
value := "Hello,学院君!"
pool.Put(value)
fmt.Println(pool.Get())
fmt.Println(pool.Get())
}
poolNewfunc() interface{}PutpoolGetpoolGetNew
sync.Poolsync.PoolPool
package main
import (
"fmt"
"sync"
)
func test_put(pool *sync.Pool, deferFunc func()) {
defer func() {
deferFunc()
}()
value := "Hello,学院君!"
pool.Put(value)
}
func main() {
var wg sync.WaitGroup
wg.Add(1)
var pool = &sync.Pool{
New: func() interface{} {
return "Hello,World!"
},
}
go test_put(pool, wg.Done)
wg.Wait()
fmt.Println(pool.Get())
}
fmt.Printlnsync.Poolprinterprinter
func newPrinter() *pp {
p := ppFree.Get().(*pp)
p.panicking = false
p.erroring = false
p.fmt.init(&p.buf)
return p
}
func (p *pp) free() {
if cap(p.buf) > 64<<10 {
return
}
p.buf = p.buf[:0]
p.arg = nil
p.value = reflect.Value{}
ppFree.Put(p)
}
ppFreesync.Pool
var ppFree = sync.Pool{
New: func() interface{} { return new(pp) },
}
sync.Pool