面试题答案
一键面试sync.Once实现单例模式的底层原理
- 保证初始化只执行一次:在Go语言中,
sync.Once
类型提供了一种机制,确保其关联的函数只被执行一次。这对于实现单例模式非常有用,因为单例模式要求某个类型的实例在整个程序生命周期中只被创建一次。 - 实现方式:
sync.Once
通过内部的一个状态标志和一个互斥锁来实现这种机制。当第一次调用Do
方法时,它会检查状态标志。如果标志表明初始化尚未进行,它会获取互斥锁,再次检查状态标志(防止在获取锁期间其他 goroutine 已经完成了初始化),然后执行传入的初始化函数,并设置状态标志。后续调用Do
方法时,由于状态标志已表明初始化完成,直接返回,不再执行初始化函数。
sync.Once结构体中各个字段的作用
sync.Once
结构体在Go标准库中的定义如下(简化版):
type Once struct {
done uint32
m Mutex
}
done
字段:- 类型为
uint32
,它是一个状态标志。其值为0时,表示初始化尚未完成;非0值表示初始化已经完成。done
字段使用原子操作来读写,以确保在多 goroutine 环境下的正确性。例如,atomic.StoreUint32
用于设置done
为非0值,表示初始化完成,atomic.LoadUint32
用于读取done
的值,判断初始化是否完成。
- 类型为
m
字段:- 类型为
Mutex
,即互斥锁。它的作用是在初始化过程中保证并发安全。当多个 goroutine 同时尝试初始化时,通过互斥锁来确保只有一个 goroutine 能够进入初始化流程,避免重复初始化。在获取锁后,还会再次检查done
标志,防止在获取锁期间其他 goroutine 已经完成了初始化,这种双重检查机制进一步提高了效率。
- 类型为