教我做网站,网商之家,广告设计与制作需要学什么专业,小程序开发需求方案sync.Once 是 Go 语言标准库中的一个结构体#xff0c;它的作用是确保某个操作在全局范围内只被执行一次。这对于实现单例模式或需要一次性初始化资源的场景非常有用。
典型用法
sync.Once 提供了一个方法 Do(f func())#xff0c;该方法接收一个没有参数和返回值的函数 f …sync.Once 是 Go 语言标准库中的一个结构体它的作用是确保某个操作在全局范围内只被执行一次。这对于实现单例模式或需要一次性初始化资源的场景非常有用。
典型用法
sync.Once 提供了一个方法 Do(f func())该方法接收一个没有参数和返回值的函数 f 作为参数。无论 Do 方法被调用多少次函数 f 只会被执行一次。
var once sync.Oncefunc setup() {// 初始化操作只会执行一次
}func main() {// 即使在多线程环境下setup函数也只会被执行一次once.Do(setup)once.Do(setup) // 这次调用不会执行setup
}
多CPU下跑 - 示例
依然只执行一次
package mainimport (fmtruntimesync
)var once sync.Once
var wg sync.WaitGroupfunc setup() {// 初始化操作只会执行一次fmt.Println(init)
}func main() {// 设置GOMAXPROCS为机器上的CPU核心数// 让协程同时跑在多个CPU上numCPU : runtime.NumCPU()runtime.GOMAXPROCS(numCPU)fmt.Printf(Running with %d CPUs\n, numCPU)// 即使在多核CPU下的多协程环境下setup函数也只会被执行一次for i : 0; i 1000; i {wg.Add(1)go func(i int) {defer wg.Done()once.Do(setup)fmt.Printf(Running in goroutine %d\n, i)}(i)}wg.Wait()fmt.Println(Done)
}
原理
sync.Once 的实现原理基于 Go 语言的内存模型和同步原语主要通过两个字段控制一个是 done用于标记函数 f 是否已经执行过另一个是互斥锁 m用于在多个 goroutine 同时调用 Do 方法时保证只有一个能执行函数 f。
当 Do 方法第一次被调用时done 字段为 0表示函数 f 还没有执行。Do 方法会先检查 done 字段如果 f 已经执行done 不为 0则直接返回。如果 f 还没有执行Do 方法会加锁并再次检查 done 字段以防在等待锁的过程中 f 被执行。如果 f 确实还没有执行Do 方法会执行函数 f然后将 done 设置为 1 并释放锁。
这种设计确保了即使在高并发的情况下函数 f 也只会被执行一次同时避免了不必要的加锁操作提高了效率。