Once
Once 能够用来执行且仅仅执行一次动作,经常用于单例对象的初始化场景。
once可用于实现单例模式中懒汉实现:
package mainimport ( "fmt" "sync")var once sync.Oncetype single struct {}var singleInstance *singlefunc getInstance() *single { if singleInstance == nil { once.Do( func() { fmt.Println("Creating single instance now.") singleInstance = &single{} }) } else { fmt.Println("Single instance already created.") } return singleInstance}func main() { for i := 0; i < 30; i++ { go getInstance() } // Scanln is similar to Scan, but stops scanning at a newline and // after the final item there must be a newline or EOF. fmt.Scanln()}
Once构造体
type Once struct { done uint32 // done 批示操作是否已执行 m Mutex}
Do
func (o *Once) Do(f func())
sync.Once 只裸露了一个办法 Do,你能够屡次调用 Do 办法,然而只有第一次调用 Do
办法时 f 参数才会执行,这里的 f 是一个无参数无返回值的函数。因为当且仅当第一次调用 Do 办法的时候参数 f 才会执行,即便第二次、第三次、第 n 次调用时 f 参数的值不一样,也不会被执行。
func (o *Once) Do(f func()) { if atomic.LoadUint32(&o.done) == 0 { // Outlined slow-path to allow inlining of the fast-path. o.doSlow(f) }}func (o *Once) doSlow(f func()) { o.m.Lock() defer o.m.Unlock() // 双重检测 // 保障了并发的 goroutine 会期待 f 实现,而且还不会屡次执行 f。 if o.done == 0 { defer atomic.StoreUint32(&o.done, 1) f() }}