DEV Community

Ash Wu
Ash Wu

Posted on

sync.Pool

#go

Official document: [https://godoc.org/sync#Pool]

The usage of sync.Pool is a very common in high concurrency scenarios. You may create tons of goroutines and each of them allocates short-lived objects and later cause a slow GC.

With sync.Pool we can avoid this. Objects inside the pool will be cleaned after GC without any notification, so sync.Pool is not suitable for connection pool.

The objects being Put() back into the pool may be Get() and reused before GC happens. This means you have the chance to Get() a object with old values.

Example here:

package main

import (
    "fmt"
    "runtime"
    "runtime/debug"
    "sync"
)

func main() {
    newFunc := func() interface{} {
        return make([]byte, 32)
    }
    pool := sync.Pool{New: newFunc}

    v1 := pool.Get().([]byte)
    fmt.Printf("v1: %v\n", v1)
    v1[0] = 1
    fmt.Printf("modified v1: %v\n", v1)

    // modified v1, put back to pool, before GC
    pool.Put(v1)
    v2 := pool.Get().([]byte)
    fmt.Printf("v2: %v\n", v2)
    pool.Put(v2)

    // After GC
    debug.SetGCPercent(100)
    runtime.GC()
    v3 := pool.Get().([]byte)
    fmt.Printf("v3: %v\n", v3)
}
Enter fullscreen mode Exit fullscreen mode

So do remember to clean the object before you Put() back, or init the object right after you Get() to prevent any accident.

Top comments (0)