千家信息网

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

发表于:2025-01-21 作者:千家信息网编辑
千家信息网最后更新 2025年01月21日,这篇文章主要讲解了"go单例怎么实现双重检测是否安全",文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习"go单例怎么实现双重检测是否安全"吧!现状当前有的项
千家信息网最后更新 2025年01月21日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安全错误 数据库的锁怎样保障安全 网络安全伴我行二年级手抄报 医院挂号预约系统数据库设计 软件开发项目计划书怎么做 数据库新建视图的方法 太仓电子网络技术包括什么 中国电信服务器中标公告 数据库软件的安装问题 蓝盟网络安全软件 开发简单股票软件开发 实时数据库转为关系数据库 合肥亮兴网络技术有限公司 物联软件开发 数据库冲突什么意思 方舟生存进化服务器开不了控制台 邮储银行软件开发中心成立时间 orop数据库 网络安全内控管理制度 小学四则运算数据库 access忘记数据库密码 新神魔大陆服务器寻宝地宫在哪里 it软件开发制作 潜山网络安全有哪些 热血传奇手游推荐哪个服务器 思科网络安全期末考试 熟悉网络管理或网络安全 服务器一个网口既能管理又能拨号 数据库表绑定显示控件 深圳软件开发销售 重生互联网科技金融小说 一万日活需要多大云服务器
0