共计 975 个字符,预计需要花费 3 分钟才能阅读完成。
Once
Once 能够用来执行且仅仅执行一次动作,经常用于单例对象的初始化场景。
once 可用于实现单例模式中懒汉实现:
package main
import (
"fmt"
"sync"
)
var once sync.Once
type single struct {
}
var singleInstance *single
func 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()}
}
正文完