zoukankan      html  css  js  c++  java
  • golang sync.Once用法

    sync.Once能确保实例化对象Do方法在多线程环境只运行一次,内部通过互斥锁实现

    Do方法

    Once类型的Do方法只接收一个参数,参数的类型必须是func(),即无参数无返回的函数。该方法的功能并不是对每一种参数函数都只执行一次,而是只执行首次被调用时传入的那个函数,并且之后不会再执行任何参数函数。所以,如果有多个需要执行一次的函数,应该为它们每一个都分配一个sync.Once类型的值。

    var once sync.Once
        for i, v := range make([]string, 10) {
            once.Do(func() {
                t.Log("function 1")
            })
        }
        for i := 0; i < 10; i++ {
            once.Do(func() {
                t.Log("function 2")
            })
        }

    这段示例代码只会输出一次“function 1”

    与init函数对比

    sync.Once 是 Golang package 中使方法只执行一次的对象实现,作用与 init 函数类似。但也有所不同。

    • init 函数是在文件包首次被加载的时候执行,且只执行一次
    • sync.Onc 是在代码运行中需要的时候执行,且只执行一次

    当一个函数不希望程序在一开始的时候就被执行的时候,我们可以使用 sync.Once 。

    源码

    sync.Once 使用变量 done 来记录函数的执行状态,使用 sync.Mutex 和 sync.atomic 来保证线程安全的读取 done 。

    func (o *Once) Do(f func()) {
        if atomic.LoadUint32(&o.done) == 0 {
            // Outlined slow-path to allow inlining of the fast-path.
            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()
        }
    }

    实现中也用到了类似double check思想

  • 相关阅读:
    NOI2017 退役记
    bzoj2590[Usaco2012 Feb]Cow Coupons
    bzoj2215[POI2011]Conspiracy
    bzoj2115[WC2011]Xor
    bzoj4754[JSOI2016]独特的树叶
    SQL外连接与条件 left outer join + WHERE/AND 区别
    IBM Datastage
    无法在MS SQL SERVER MANAGEMENT中打开SSIS实例-解决办法
    SSIS 教学教程
    SQL SERVER 2019 电子书下载
  • 原文地址:https://www.cnblogs.com/luoming1224/p/14713998.html
Copyright © 2011-2022 走看看