最近代码中需要使用sync.Once,mark下心得~
sync.Once顾名思义,就是能够实现多线程同步执行,且只执行一次,多用于单例模式。
如某个单例,在访问时才进行创建并初始化,这里就可以使用sync.Once。
sync.Once的源码如下,go版本1.12.7 windows/amd64:
package sync
import (
"sync/atomic"
)
type Once struct {
m Mutex
done uint32
}
func (o *Once) Do(f func()) {
// 先检查o.done是否完成
if atomic.LoadUint32(&o.done) == 1 {
return
}
// Slow-path.
// 加锁,避免多线程调用f()
o.m.Lock()
defer o.m.Unlock()
if o.done == 0 {
defer atomic.StoreUint32(&o.done, 1)
f()
}
}
说白了就是一个标识是否完成的标志,以及一个互斥量,并通过原子操作来读/写这个标志。
单例样例:
type Config struct {
Name string
}
var c *Config
func getConfig() *Config {
once.Do(func() {
if c != nil {
return
}
c = &Config{
Name: "test",
}
})
return c
}