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思想

  • 相关阅读:
    Linux之流程判断
    Linux之Shell变量
    Linux之RAID
    Y-Sport
    [ST2017] Lab1: Triangle type and Junit test
    [ST2017] Hw3: Prime Path
    [ST2017] Hw2: Fault, Error, Failure and test case for projects
    [SPM2017] Hw1: The outcome of my project [Deadline: 23:59:59, Mar.1, 2017]
    [ST2017] Hw1: An error from my past projects [Deadline: 23:59:59, Feb.27, 2017]
    一个使用Jmeter做接口性能测试的实战案例
  • 原文地址:https://www.cnblogs.com/luoming1224/p/14713998.html
Copyright © 2011-2022 走看看