首页 > 后端开发 > Golang > 正文

如何使用Golang实现单例模式线程安全_使用Singleton Pattern防止并发冲突

P粉602998670
发布: 2025-12-20 16:20:02
原创
878人浏览过
Go中实现线程安全单例应优先使用sync.Once,它保证初始化函数仅执行一次且自带同步语义;避免手动实现双重检查锁定(DCL),因其在Go中冗余、易错且不安全;支持带错误返回的初始化需配合全局err变量与once.Do闭包。

如何使用golang实现单例模式线程安全_使用singleton pattern防止并发冲突

在 Go 语言中实现线程安全的单例模式,核心是避免多个 goroutine 同时初始化实例导致重复创建或竞态。Go 提供了简洁高效的原语(如 sync.Once)来解决这个问题,无需手动加锁或双重检查锁定(DCL)——后者在 Go 中不仅冗余,还容易出错。

用 sync.Once 实现最简线程安全单例

sync.Once 保证其包裹的函数只执行一次,且自带同步语义,天然适合单例初始化场景。这是 Go 官方推荐、最可靠的方式。

  • 定义一个私有全局变量(如 instance *Singleton)和一个 sync.Once 实例
  • 提供一个公开的获取函数(如 GetInstance()),内部调用 once.Do() 来惰性创建实例
  • 所有并发调用 GetInstance() 都会阻塞直到首次创建完成,之后直接返回已创建的实例

示例代码:

var (
    instance *Singleton
    once     sync.Once
)

type Singleton struct {
    data string
}

func GetInstance() *Singleton {
    once.Do(func() {
        instance = &Singleton{data: "initialized"}
    })
    return instance
}
登录后复制

避免常见陷阱:不要用双重检查锁定(DCL)

有些开发者习惯从 Java 或 C++ 移植 DCL 写法(先判空 → 加锁 → 再判空 → 初始化),但在 Go 中这既不必要也不安全:

立即学习go语言免费学习笔记(深入)”;

  • sync.Once 已经高效处理了“仅一次”和内存可见性问题
  • 手动实现 DCL 容易因缺少内存屏障(如 atomic.StorePointer)导致读取到未完全构造的对象
  • 代码更长、可读性差、维护成本高

除非有特殊需求(如需延迟初始化前做复杂条件判断),否则坚决不用 DCL。

Seed-TTS
Seed-TTS

Seed-TTS 是一个高质量多功能的文本到语音生成模型

Seed-TTS 909
查看详情 Seed-TTS

支持带参数或错误的初始化

如果单例初始化可能失败(如连接数据库、读配置),可将初始化逻辑封装为一个私有函数,返回实例和 error,并在 once.Do 中调用它。注意:error 本身不能通过 sync.Once 直接暴露,需额外存储。

  • 声明 var err error 全局变量配合 once
  • once.Do 的闭包中执行初始化并赋值 instanceerr
  • 对外提供 GetInstance()InitError() 两个函数,或统一返回 (*Singleton, error)

这样既保持线程安全,又支持错误传播。

测试并发安全性很简单

写一个并发调用 GetInstance() 的测试,验证是否始终返回同一地址、且初始化逻辑只执行一次:

func TestSingletonConcurrent(t *testing.T) {
    var wg sync.WaitGroup
    instances := make([]*Singleton, 100)
    
    for i := 0; i < 100; i++ {
        wg.Add(1)
        go func(j int) {
            defer wg.Done()
            instances[j] = GetInstance()
        }(i)
    }
    wg.Wait()
    
    // 所有指针应相等
    for i := 1; i < len(instances); i++ {
        if instances[i] != instances[0] {
            t.Fatal("not singleton!")
        }
    }
}
登录后复制

基本上就这些 —— 简洁、安全、符合 Go 习惯。

以上就是如何使用Golang实现单例模式线程安全_使用Singleton Pattern防止并发冲突的详细内容,更多请关注php中文网其它相关文章!

最佳 Windows 性能的顶级免费优化软件
最佳 Windows 性能的顶级免费优化软件

每个人都需要一台速度更快、更稳定的 PC。随着时间的推移,垃圾文件、旧注册表数据和不必要的后台进程会占用资源并降低性能。幸运的是,许多工具可以让 Windows 保持平稳运行。

下载
来源:php中文网
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn
最新问题
开源免费商场系统广告
热门教程
更多>
最新下载
更多>
网站特效
网站源码
网站素材
前端模板
关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号