Open dccmmtop opened 2 years ago
用来约束创建和复用昂贵的场景,比如数据库连接
通过 sync.Pool 包实现,并发安全
sync.Pool
package main import( "fmt" "sync" ) func main(){ myPool := sync.Pool{ New: func() interface{} { fmt.Println("创建一个新的实例") return struct{}{} }, } // 第一次取,池中没有实例,要新建 myPool.Get() // 第二次取,池中也没有实例,因为没有把第一次取得实例放入到池中, 要新建 instance := myPool.Get() // 将取到得实例放入池中 myPool.Put(instance) // 池中已经有实例,不用新建 myPool.Get() // 所以会输出 2 次结果 }
结果:
package main import( "fmt" "sync" "time" "strconv" "os" ) func main(){ numCalcsCreated := 0 calcPool := &sync.Pool{ New: func() interface{} { numCalcsCreated ++ // 使用了 1Kb 的内存 mem := make([]byte,1024) return &mem }, } calcPool.Put(calcPool.New()) calcPool.Put(calcPool.New()) calcPool.Put(calcPool.New()) calcPool.Put(calcPool.New()) const numWorks = 1024 var wg sync.WaitGroup wg.Add(numWorks) sleepTime, err := strconv.Atoi(os.Args[1]) if err != nil { fmt.Println(err) return } for i := 0; i < numWorks ; i ++ { go func(){ defer wg.Done() // 使用池化技术,每次用完之后,立即放入池中,永远只会使用少量的实例 // 也有可能归还太慢,导致用池中暂时没有实例可用,从而继续生成新的实例 mem := calcPool.Get() time.Sleep(time.Duration(sleepTime) * time.Nanosecond) defer calcPool.Put(mem) }() } wg.Wait() fmt.Println("创建了",numCalcsCreated, "次") }
调整休眠时间,运行结果如下
为什么需要池
用来约束创建和复用昂贵的场景,比如数据库连接
Go是怎么实现的池
通过
sync.Pool
包实现,并发安全怎么使用
示例
结果:
第二个例子
调整休眠时间,运行结果如下