zoukankan      html  css  js  c++  java
  • go中sync.Once源码解读

    sync.Once

    前言

    本次的代码是基于go version go1.13.15 darwin/amd64

    sync.Once的作用

    根据名字就大致能猜到这个函数的作用,就是使用sync.once的对象只能执行一次。

    我们在errgroup就能看到它的身影

    type Group struct {
    	cancel func()
    
    	wg sync.WaitGroup
    
    	errOnce sync.Once
    	err     error
    }
    

    他保证了,只会记录第一个出错的goroutine的错误信息

    实现原理

    // Once is an object that will perform exactly one action.
    type Once struct {
    	// 0未执行,1执行了
    	done uint32
    	// 互斥锁
    	m    Mutex
    }
    

    里面就一个对外的函数

    func (o *Once) Do(f func()) {
    	// 原子的读取done的值,如果为0代表onec第一次的执行还没有出发
    	if atomic.LoadUint32(&o.done) == 0 {
    		// 执行
    		o.doSlow(f)
    	}
    }
    
    func (o *Once) doSlow(f func()) {
    	// 加锁
    	o.m.Lock()
    	defer o.m.Unlock()
    	// 判断done变量为0表示还没执行第一次
    	if o.done == 0 {
    		// 计数器原子的加一
    		defer atomic.StoreUint32(&o.done, 1)
    		// 执行传入的函数
    		f()
    	}
    }
    

    总结

    1、总体上也是很简单一个计数器,一把互斥锁,通过atomic.LoadUint32的原子读取技术器中的值;

    2、如果计数器中的值为0表示还没有执行;

    3、加锁,执行传入的函数,然后通过atomic.StoreUint32原子的对计数器的值进行加一操作;

    4、完成。

  • 相关阅读:
    RPC中阻塞队列的作用
    记用tensorflow-ranking时的bugs
    JDK作泛型比较时为什么把逻辑代码写两遍
    Java 不能声明泛型数组
    QuickSort Hoare vs Lomuto
    Java 对数组扩容
    Java交换两对象的问题
    毕业 失业
    dependencyManagement介绍
    web笔记
  • 原文地址:https://www.cnblogs.com/ricklz/p/14503674.html
Copyright © 2011-2022 走看看