GoLang sync 模块介绍

2017-06-11 language golang

Pool

一般超过几百个字节后建议使用,否则可能会因为该机制带来更大的性能损耗,造成过渡优化。

package main

import (
	"fmt"
	"sync"
)

type Person struct {
	Name string
}
func (p *Person) String() string {
	return fmt.Sprintf("<%s(%p)>", p.Name, p)
}

func main() {
	pool :=	&sync.Pool{
		New: func() interface{} {
			fmt.Println("Create a new person")
			return new(Person)
		},
	}
	p := pool.Get().(*Person)
	p.Name = "Andy"
	fmt.Printf("Got %v.\n", p)
	pool.Put(p)
	fmt.Printf("Got %v.\n", pool.Get().(*Person))
	fmt.Printf("Got %v.\n", pool.Get().(*Person))
}

上述代码会输出如下内容。

Create a new person
Got <Andy(0xc000012d50)>.
Got <Andy(0xc000012d50)>.
Create a new person
Got <(0xc000012d80)>.

可以看到,第二次是直接使用之前申请的对象,而且没有将对象复位 (使用时也不要用此时间);当第三次申请时,会重新申请一个对象。

模块使用

在标准模块中也会使用 Pool 来缓存对象,例如 fmt 模块。

fmt.Printf()
 |-fmt.Fprintf()
   |-fmt.newPrinter()
   | |-ppFree.Get()     从sync.Pool中获取对象,并初始化buf成员
   |-pp.doPrintf()
   |-io.Writer.Write()
   |-pp.free() 
     |-ppFree.Put()

pp.free() 函数中,为了尽量保证缓存池中对象大小的均衡,如果其中的缓冲区超过了大小,那么就不再放回到缓冲池中。