MST

星途 面试题库

面试题:Go语言sync.Once单例模式在并发场景下的优化

在高并发场景下,使用Go语言的sync.Once实现单例模式可能会遇到性能瓶颈。请阐述可能出现性能问题的地方,并提出至少一种优化方案,说明优化的原理及实现思路。
39.5万 热度难度
编程语言Go

知识考点

AI 面试

面试题答案

一键面试

可能出现性能问题的地方

  1. 竞争锁开销sync.Once内部使用了互斥锁(mutex),在高并发场景下,大量的Do方法调用会频繁竞争这个锁,导致锁的争用严重,增加上下文切换和调度开销,从而降低系统整体性能。

优化方案

  1. 双检锁机制优化
    • 原理:通过在调用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
}
  1. 基于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
}