golang学习———sync.Once(2)

wang_zong_sheng · · 2008 次点击 · · 开始浏览    
这是一个创建于 的文章,其中的信息可能已经有所发展或是发生改变。

在开发时,我们经常碰到这样的应用场景:只需要执行或初始化一次,例如,单例模式或是系统开启时的初始化。一般的语言通用做法是利用互斥操作设置标志变量,通过判断标志变量的值决定是否执行相关代码;golang语言的实现非常简单,只需一行代码,如下:

        import "sync"

var once sync.Once

func init() {

    //初始化代码

}


once.Do(init) // 只需一行代码,结构清晰,一目了然

那么once.Do()这个方法是如何实现的呢?我们来解析golang实现的一次操作:

    首先, “sync” 是一个引用的包,具体实现在该包中; Once是定义的一个结构体对象,如下:

     type Once struct {

           m Mutex

           done uint32

     }

     看到这里,我们基本应该可以猜出once.Do()的实现思路,Once.m是一个互斥锁,在进行Do()操作时,进行互斥操作;Once.done是一个标志变量,表示是否进行过Do()的操作。Do()的具体实现如下:

    func (o *Once) Do(f func()) {

        if atomic.LoadUint32(&o.done) == 1 {

return

        }

        o.m.Lock()

        defer o.m.Unlock()

        if o.done == 0 {

     defer automic.StoreUint32(&o.done, 1)

             f()

}

    }

    实现思路与我们的猜测基本一致,它引入了原子操作包  import "sync/atomic",通过automic.LoadUint32和automic.StoreUint32操作实现标志变量Once.done的载入和存储,这样更精细化的原子操作的实现能进一步提高系统处理的速度,减少协程对互斥锁不必要的等待。


有疑问加站长微信联系(非本文作者)

本文来自:CSDN博客

感谢作者:wang_zong_sheng

查看原文:golang学习———sync.Once(2)

入群交流(和以上内容无关):加入Go大咖交流群,或添加微信:liuxiaoyan-s 备注:入群;或加QQ群:692541889

2008 次点击  
加入收藏 微博
暂无回复
添加一条新回复 (您需要 登录 后才能回复 没有账号 ?)
  • 请尽量让自己的回复能够对别人有帮助
  • 支持 Markdown 格式, **粗体**、~~删除线~~、`单行代码`
  • 支持 @ 本站用户;支持表情(输入 : 提示),见 Emoji cheat sheet
  • 图片支持拖拽、截图粘贴等方式上传