1 回答
TA贡献1785条经验 获得超4个赞
让我们将您的问题分解为两部分:
单例
原子和 Go 内存模型
单例
Go 有包级变量。这些是在任何东西有机会移动之前实例化的,因此,如果您在使用包后立即创建这些东西,您将免费获得一个单身人士。
package somepack
var(
connection = createConn()
)
func Connection() SomeConnection {
return connection
}
connection将被创建一次,因此Connection()将安全地返回它的相同实例。
有时,开发人员在需要“惰性”实例化时会使用单例。如果资源的创建成本很高且并非总是需要,那么这是一个好主意。这是sync.Once有用的地方。
var (
connection SomeConnection // Not instantiated
connectionOnce sync.Once
)
func Connection() SomeConnection {
connectionOnce.Do(func(){
connection = createConn()
})
return connection
}
请注意,我没有对作业做任何特别的事情(例如,atomic.Store())。这是因为sync.Once处理了所有需要的锁定以确保安全。
原子和 Go 内存模型
一个很好的开始资源是为此发布的文档:The Go Memory Model
您对“刷新”到不同 CPU 的担忧是有效的(尽管有一些评论),因为每个 CPU 都有自己的缓存和自己的状态。C++(以及 Rust 等其他语言)开发人员倾向于关心这一点,因为他们会关心这一点。Go 开发人员不会太在意,因为 Go 只有“以前发生过”。Rust 实际上有一些不错的文档。
话虽这么说,你通常不需要担心它。互斥锁(和sync.Once)将强制每个 CPU 上的内存状态达到您所期望的状态。
- 1 回答
- 0 关注
- 87 浏览
添加回答
举报