登录
首页 >  Golang >  Go问答

使用sync.Once实现绝对单例?

来源:stackoverflow

时间:2024-03-10 08:18:26 134浏览 收藏

来到golang学习网的大家,相信都是编程学习爱好者,希望在这里学习Golang相关编程知识。下面本篇文章就来带大家聊聊《使用sync.Once实现绝对单例?》,介绍一下,希望对大家的知识积累有所帮助,助力实战开发!

问题内容

我很困惑,下面的代码片段是否完美?

import "sync"
import "sync/atomic"

var initialized uint32
var instance *singleton

var instance *singleton
var once sync.once

func getinstance() *singleton {
    once.do(func() {
        instance = &singleton{}
    })
    return instance
}

atomic.storeuint32(&initialized, 1) 会将实例刷新到所有 cpu? 我想我需要添加一个原子存储并加载,例如下面的代码片段

var instance *singleton
var once sync.once

func getinstance() *singleton {
    once.do(func() {
        atomic.storepointer(&instance, &singleton{})
    })
    return atomic.loadpointer(&instance)
}

我认为once.do只是保证函数f执行一次。 和 atomic.storeuint32(&o.done, 1) 只是 o.done 的内存屏障。 它不能确保 instance 全局可见

func (o *Once) Do(f func()) {
    if atomic.LoadUint32(&o.done) == 1 {
        return
    }
    // Slow-path.
    o.m.Lock()
    defer o.m.Unlock()
    if o.done == 0 {
        defer atomic.StoreUint32(&o.done, 1)
        f()
    }
}

解决方案


让我们将您的问题分成两部分:

  1. 单身人士
  2. 原子和 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 上有一些不错的 docs

话虽如此,您通常不需要担心它。互斥体(和 sync.once)将强制每个 cpu 上的内存状态达到您所期望的状态。

以上就是本文的全部内容了,是否有顺利帮助你解决问题?若是能给你带来学习上的帮助,请大家多多支持golang学习网!更多关于Golang的相关知识,也可关注golang学习网公众号。

声明:本文转载于:stackoverflow 如有侵犯,请联系study_golang@163.com删除
相关阅读
更多>
最新阅读
更多>
课程推荐
更多>