文章详情

短信预约-IT技能 免费直播动态提醒

请输入下面的图形验证码

提交验证

短信预约提醒成功

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

2023-06-29 10:45

关注

这篇文章主要讲解了“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<b.N;i++{        go getInstance()

是否线程安全

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

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

可以看到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<b.N;i++{        go getInstance()    }

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

race检测结果:

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

没有发生竞态

关于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单例怎么实现双重检测是否安全这一问题有了更深刻的体会,具体使用情况还需要大家实践验证。这里是编程网,小编将为大家推送更多相关知识点的文章,欢迎关注!

阅读原文内容投诉

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

软考中级精品资料免费领

  • 历年真题答案解析
  • 备考技巧名师总结
  • 高频考点精准押题
  • 2024年上半年信息系统项目管理师第二批次真题及答案解析(完整版)

    难度     807人已做
    查看
  • 【考后总结】2024年5月26日信息系统项目管理师第2批次考情分析

    难度     351人已做
    查看
  • 【考后总结】2024年5月25日信息系统项目管理师第1批次考情分析

    难度     314人已做
    查看
  • 2024年上半年软考高项第一、二批次真题考点汇总(完整版)

    难度     433人已做
    查看
  • 2024年上半年系统架构设计师考试综合知识真题

    难度     221人已做
    查看

相关文章

发现更多好内容

猜你喜欢

AI推送时光机
位置:首页-资讯-后端开发
咦!没有更多了?去看看其它编程学习网 内容吧
首页课程
资料下载
问答资讯