面试题答案
一键面试性能瓶颈原因分析
sync.Once
的性能瓶颈主要在于其内部使用了互斥锁 Mutex
。在高并发场景下,多个协程同时尝试执行初始化操作时,由于 Mutex
的存在,只有一个协程能够进入临界区执行初始化代码,其他协程都需要等待锁的释放。这就导致大量协程处于阻塞状态,增加了协程调度开销,降低了系统的并发性能。
优化方案
- 懒汉式初始化:只有在真正需要使用共享资源时才进行初始化,并且在初始化时使用双重检查锁定(Double-Check Locking)机制来减少锁的竞争。
- 预初始化:在服务启动时,提前初始化好共享资源,避免在高并发阶段进行初始化操作。
代码示例(懒汉式初始化)
package main
import (
"fmt"
"sync"
)
type Resource struct {
// 这里可以定义资源的具体结构,比如数据库连接池的配置等
data string
}
var (
resourceInstance *Resource
once sync.Once
mu sync.Mutex
)
func GetResource() *Resource {
if resourceInstance != nil {
return resourceInstance
}
mu.Lock()
defer mu.Unlock()
if resourceInstance == nil {
resourceInstance = &Resource{
data: "初始化的数据",
}
}
return resourceInstance
}
func main() {
var wg sync.WaitGroup
for i := 0; i < 10; i++ {
wg.Add(1)
go func() {
defer wg.Done()
res := GetResource()
fmt.Println(res.data)
}()
}
wg.Wait()
}
代码示例(预初始化)
package main
import (
"fmt"
"sync"
)
type Resource struct {
// 这里可以定义资源的具体结构,比如数据库连接池的配置等
data string
}
var resourceInstance *Resource
func init() {
resourceInstance = &Resource{
data: "预初始化的数据",
}
}
func GetResource() *Resource {
return resourceInstance
}
func main() {
var wg sync.WaitGroup
for i := 0; i < 10; i++ {
wg.Add(1)
go func() {
defer wg.Done()
res := GetResource()
fmt.Println(res.data)
}()
}
wg.Wait()
}