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)
}
推荐阅读
- Go函数学习
- GoTests 工具自动化 test 使用
- 9张图轻松吃透Go内存管理单元
- Go内存架构,一个有趣的问题
- Go 语言第一课--核心篇
- GoLang底层|GoLang之切片底层系列二(浅显学习)
- 在从Golang Buffalo webapp发送推文时设置CSRF令牌时遇到问题
- 使用Air热加载Go程序(windows下的配置)
- Go语言将引入新型排序算法(pdqsort)