golang sync 包

sync.Pool 的分享,关于适用场景:
当多个 goroutine 都需要创建同?个对象的时候,如果 goroutine 数过多,导致对象的创建数?剧增,进?导致 GC 压?增大。形成 “并发?-占?内存?-GC 缓慢-处理并发能?降低-并发更?”这样的恶性循环。 在这个时候,需要有?个对象池,每个 goroutine 不再??单独创建对象,?是从对象池中获取出?个对象(如果池中已经有的话)。
因此关键思想就是对象的复用,避免重复创建、销毁,下面我们来看看如何使用。
所以,sync.pool 的作用一句话描述就是,复用临时对象,以避免频繁的内存分配和回收,从而减少 GC 压力。
sync.Pool 是协程安全的,这对于使用者来说是极其方便的。使用前,设置好对象的 New 函数,用于在 Pool 里没有缓存的对象时,创建一个。之后,在程序的任何地方、任何时候仅通过 Get()、Put() 方法就可以取、还对象了。
【golang sync 包】sync.Cond 使用
Golang 的 sync 包中的 Cond 实现了一种条件变量,可以使用在多个Reader等待共享资源 ready 的场景(如果只有一读一写,一个锁或者channel就搞定了)。
Cond的汇合点:多个goroutines等待、1个goroutine通知事件发生。
比较适合任务调用场景,一个 Master goroutine 通知事件发生,多个 Worker goroutine 在资源没准备好的时候就挂起,等待通知。

// 创建Cond cond := sync.NewCond(new(sync.Mutex)) // 挂起goroutine cond.L.Lock() cond.Wait() // 唤醒一个 cond.Signal() // 唤醒所有 cond.Broadcast()

基本使用大概是需要等待的时候通过 Wait() 将 Goroutine 挂起,资源准备好的时候再通过 Signal() 或者 Broadcast() 将挂起中的 Goroutine 唤醒。
package mainimport ( "fmt" "sync" "time" )func main() { var ( locker sync.Mutex cond= sync.NewCond(&locker) wgsync.WaitGroup )for i := 0; i < 10; i++ { wg.Add(1) go func(number int) { // wait()方法内部是先释放锁 然后在加锁 所以这里需要先 Lock() cond.L.Lock() defer cond.L.Unlock() cond.Wait() // 等待通知,阻塞当前 goroutinefmt.Printf("g %v ok~ \n", number) wg.Done() }(i) }for i := 0; i < 5; i++ { // 每过 100毫秒 唤醒一个 goroutine cond.Signal() time.Sleep(time.Millisecond * 100) } time.Sleep(time.Millisecond * 100)// 剩下5个 goroutine 一起唤醒 cond.Broadcast() fmt.Println("Broadcast...") wg.Wait() }func add(a, b int) int { return a + b }func Fib(n int) int { if n < 2 { return n } return Fib(n-1) + Fib(n-2) }

    推荐阅读