go单例怎么实现双重检测是否安全
go单例怎么实现双重检测是否安全
这篇文章主要讲解了“go单例怎么实现双重检测是否安全”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“go单例怎么实现双重检测是否安全”吧!
现状
当前有的项目直接使用Mutex锁,有的就直接判断nil则创建,对于前者,每次都加锁性能差,对于后者则会出现多个实例,也就不是单例了
改进
进而想要改进一下,在这不讨论饿汉和线程非安全的实现,对于go中线程安全的懒汉实现,常见两种:
双重检验sync.Once
双重检验示例:
packagemainimport("sync""testing")var(instance*intlocksync.MutexfuncgetInstance()*int{ifinstance==nil{lock.Lock()deferlock.Unlock()ifinstance==nil{i:=1instance=&i}}returninstance}//用于下边基准测试funcBenchmarkSprintf(b*testing.B){fori:=0;i 基于java中双重检验锁的经验,因为jvm的内存模型,双重检验锁会出现可见性问题,可以通过 volatile解决 可以看到20行的写入和14行的读取发生了竞态 我们看另一种实现:sync.Once方法 packagemainimport("sync""testing")var(instance*intoncesync.OncefuncgetInstance()*int{once.Do(func(){ifinstance==nil{i:=1instance=&i}})returninstance}funcBenchmarkSprintf(b*testing.B){fori:=0;i 实现比双重检验看起来要整洁许多 race检测结果: 没有发生竞态 那么sync.Once是怎么实现的呢 看下源码: packagesyncimport("sync/atomic")typeOncestruct{doneuint32mMutex}func(o*Once)Do(ffunc()){ifatomic.LoadUint32(&o.done)==0{o.doSlow(f)}func(o*Once)doSlow(ffunc()){o.m.Lock()defero.m.Unlock()ifo.done==0{deferatomic.StoreUint32(&o.done,1)f() 可以看到sync.Once内部其实也是一个双重检验锁,但是对于共享变量(done字段)的读和写使用了atomic包的StoreUint32和LoadUint32方法 sync.Once使用一个32位无符号整数表示共享变量,即使是32位变量的读写操作都需要atomic包方法来实现原子性,更说明了go里边指针的读写不能保证原子性 感谢各位的阅读,以上就是“go单例怎么实现双重检测是否安全”的内容了,经过本文的学习后,相信大家对go单例怎么实现双重检测是否安全这一问题有了更深刻的体会,具体使用情况还需要大家实践验证。这里是恰卡编程网,小编将为大家推送更多相关知识点的文章,欢迎关注!是否线程安全
那么在go里会有类似问题吗?
关键点在于instance变量的读和写是否是原子操作
这里做了个race竞态检测:
上例中用64位(系统是64位)的int指针表示一个实例,也说明了对于64位数据的写入和读取是非原子操作关于sync.Once
推荐阅读
-
go如何实现职责链模式
go如何实现职责链模式这篇文章主要讲解了“go如何实现职责链模式”...
-
Go Callvis如何使用
GoCallvis如何使用今天小编给大家分享一下GoCallv...
-
go pprof如何使用
gopprof如何使用这篇文章主要介绍“gopprof如何使用...
-
Go框架三件套Gorm、Kitex、Hertz怎么使用
Go框架三件套Gorm、Kitex、Hertz怎么使用本篇内容介绍...
-
Go语言单元测试和基准测试实例代码分析
Go语言单元测试和基准测试实例代码分析本篇内容主要讲解“Go语言单...
-
go Realize怎么使用
goRealize怎么使用本文小编为大家详细介绍“goReal...
-
14天学会Go语言第四天:Array Map Slice 数组 和切片
-
如何从 PHP 过渡到 Golang?
我是PHP开发者,转Go两个月了吧,记录一下使用Golang怎么一步步开发新项目。本着有坑填坑,有错改错的宗...
-
零经验Go语言MVC框架,并推荐PHP函数库和MySQL表自动转struct
最近搭建k8s系统,为了调试自动部署用Go做了个MVC框架,这是个适用于喜欢Go语言练习的框架,零Go语言经验学习Go;配合Go模...
-
从php到Golang系统的演变