可能出现性能问题的地方
- 竞争锁开销:
sync.Once
内部使用了互斥锁(mutex
),在高并发场景下,大量的Do
方法调用会频繁竞争这个锁,导致锁的争用严重,增加上下文切换和调度开销,从而降低系统整体性能。
优化方案
- 双检锁机制优化:
- 原理:通过在调用
Once.Do
之前先进行一次无锁检查,只有在实例尚未初始化时才进入Once.Do
进行初始化。这样大部分情况下可以避免锁的竞争,只有在首次初始化时才需要竞争锁。
- 实现思路:
package main
import (
"fmt"
"sync"
)
type Singleton struct {
data string
}
var instance *Singleton
var once sync.Once
var mu sync.Mutex
func GetInstance() *Singleton {
if instance == nil {
mu.Lock()
defer mu.Unlock()
if instance == nil {
instance = &Singleton{
data: "initial data",
}
}
}
return instance
}
- 基于
init
函数提前初始化:
- 原理:利用Go语言包的初始化机制,在包加载时就完成单例的初始化,避免运行时的并发初始化问题,也就不存在锁的竞争问题。
- 实现思路:
package main
import (
"fmt"
)
type Singleton struct {
data string
}
var instance *Singleton
func init() {
instance = &Singleton{
data: "initial data",
}
}
func GetInstance() *Singleton {
return instance
}