千家信息网

go单例怎么实现双重检测是否安全

发表于:2025-11-15 作者:千家信息网编辑
千家信息网最后更新 2025年11月15日,这篇文章主要讲解了"go单例怎么实现双重检测是否安全",文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习"go单例怎么实现双重检测是否安全"吧!现状当前有的项
千家信息网最后更新 2025年11月15日go单例怎么实现双重检测是否安全

这篇文章主要讲解了"go单例怎么实现双重检测是否安全",文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习"go单例怎么实现双重检测是否安全"吧!

现状

当前有的项目直接使用Mutex锁,有的就直接判断nil则创建,对于前者,每次都加锁性能差,对于后者则会出现多个实例,也就不是单例了

改进

进而想要改进一下,在这不讨论饿汉和线程非安全的实现,对于go中线程安全的懒汉实现,常见两种:

双重检验sync.Once

双重检验示例:

package main import (    "sync"    "testing")var (    instance *int    lock      sync.Mutexfunc getInstance() *int {    if instance == nil {        lock.Lock()        defer lock.Unlock()        if instance == nil {            i := 1            instance = &i        }    }    return instance}// 用于下边基准测试func BenchmarkSprintf(b *testing.B){    for i:=0;i

是否线程安全

基于java中双重检验锁的经验,因为jvm的内存模型,双重检验锁会出现可见性问题,可以通过 volatile解决
那么在go里会有类似问题吗?
关键点在于instance变量的读和写是否是原子操作
这里做了个race竞态检测:

可以看到20行的写入和14行的读取发生了竞态
上例中用64位(系统是64位)的int指针表示一个实例,也说明了对于64位数据的写入和读取是非原子操作

我们看另一种实现:sync.Once方法

package main import (    "sync"    "testing")var (    instance *int    once      sync.Oncefunc getInstance() *int {    once.Do(func(){        if instance == nil {            i := 1            instance = &i        }    })    return instance}func BenchmarkSprintf(b *testing.B){    for i:=0;i

实现比双重检验看起来要整洁许多

race检测结果:

没有发生竞态

关于sync.Once

那么sync.Once是怎么实现的呢

看下源码:

package sync import (   "sync/atomic")type Once struct {   done uint32   m    Mutex}func (o *Once) Do(f func()) {   if atomic.LoadUint32(&o.done) == 0 {      o.doSlow(f)   }func (o *Once) doSlow(f func()) {   o.m.Lock()   defer o.m.Unlock()   if o.done == 0 {      defer atomic.StoreUint32(&o.done, 1)      f()

可以看到sync.Once内部其实也是一个双重检验锁,但是对于共享变量(done字段)的读和写使用了atomic包的StoreUint32和LoadUint32方法

sync.Once使用一个32位无符号整数表示共享变量,即使是32位变量的读写操作都需要atomic包方法来实现原子性,更说明了go里边指针的读写不能保证原子性

感谢各位的阅读,以上就是"go单例怎么实现双重检测是否安全"的内容了,经过本文的学习后,相信大家对go单例怎么实现双重检测是否安全这一问题有了更深刻的体会,具体使用情况还需要大家实践验证。这里是,小编将为大家推送更多相关知识点的文章,欢迎关注!

安全 检测 检验 原子 变量 方法 线程 问题 学习 内容 实例 指针 明了 整洁 这不 中用 关键 关键点 内存 可以通过 数据库的安全要保护哪些东西 数据库安全各自的含义是什么 生产安全数据库录入 数据库的安全性及管理 数据库安全策略包含哪些 海淀数据库安全审计系统 建立农村房屋安全信息数据库 易用的数据库客户端支持安全管理 连接数据库失败ssl安全错误 数据库的锁怎样保障安全 删除数据库的命令关键词是啥 山西有哪些网络技术有限公司 东厂小说软件开发 判断服务器上文件是否存在 电视台网络安全整改情况报告 数据库中如何取年份 宁泽涛视频软件开发 动感灯箱编程软件开发 电脑自动关机软件开发 小程序数据库被黑了 数据库无法加载文件 根据网络安全法关键信息每年 河北省单招软件开发 闪耀暖暖各个服务器可以连通吗 民办大学经营在网络技术上的特点 远程服务器目录怎么取消挂载 华为服务器产品文档在哪儿下载 上海金迅瑞博网络技术有限公司 网络安全等级安全ppt课件 园区租房网络安全 深圳卓尔互联网科技有限公司 服务器安装obs及直播伴侣 数据库取出某一条 万一国互联网科技有限公司 部署网络安全管理工作 联通杯网络安全知识竞赛答案 公安行业软件开发商 上海可娱网络技术有限公司 网游服务器对数据库性能要求 sd数据库的英文
0