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思想
golang sync.Once用法的更多相关文章
- golang 常量的用法
1.Golang常量的用法 //常量的用法 var num int num =9 //1.常量声明的时候必须赋值 const tax int = 0 //2.常量值是无法修改的 //tax = 10 ...
- Golang Sync.WaitGroup 使用及原理
Golang Sync.WaitGroup 使用及原理 使用 func main() { var wg sync.WaitGroup for i := 0; i < 10; i++ { wg.A ...
- Golang sync.WaitGroup的用法
0x01 介绍 经常会看到以下了代码: 12345678910111213 package main import ( "fmt" "time") func m ...
- golang sync.noCopy 类型 —— 初探 copylocks 与 empty struct
问题引入 学习golang(v1.16)的 WaitGroup 代码时,看到了一处奇怪的用法,见下方类型定义: type WaitGroup struct { noCopy noCopy ... } ...
- golang sync/atomic
刚刚学习golang原子操作处理的时候发现github上面一个比较不错的golang学习项目 附上链接:https://github.com/polaris1119/The-Golang-Standa ...
- Golang:sync.Map
由于map在gorountine 上不是安全的,所以在大量并发读写的时候,会出现错误. 在1.9版的时候golang推出了sync.Map. sync.Map 通过阅读源码我们发现sync.Map是通 ...
- golang sync包
sync 在golang 文档上,golang不希望通过共享内存来进行进程间的协同操作,而是通过channel的方式来进行,当然,golang也提供了共享内存,锁等机制进行协同操作的包: 互斥锁: M ...
- golang包time用法详解
在我们编程过程中,经常会用到与时间相关的各种务需求,下面来介绍 golang 中有关时间的一些基本用法,我们从 time 的几种 type 来开始介绍. 时间可分为时间点与时间段,golang 也不例 ...
- golang(11) 反射用法详解
原文链接:http://www.limerence2017.com/2019/10/14/golang16/ 反射是什么 反射其实就是通过变量动态获取其值和类型的一种技术,有些语言是支持反射的比如py ...
- golang sync.Cond条件变量的使用
cond.Wait()的操作实际上是对与cond绑定的锁先进行解锁,在等待通知:接收到通知后,会尝试加锁,加锁成功则唤醒否则继续等待通知: cond.Waite()前必须对关连锁加锁,否则panic ...
随机推荐
- SPI接口(续一)
SPI接口共涉及到11个寄存器,下面就来对它们进行具体分析. 先来看SPI配置寄存器CFG,下表是它的全部位结构,其地址分别为0x40058000(SPI0),0x4005C000(SPI1). (1 ...
- 37.Spring注解相关面试题
1.@Resource和@Autowired 区别 2.@Repository.@Component.@Service.@Controller 区别
- Linux系统备份与还原——dump备份命令
dump是Linux下非常好用的备份工具,系统默认没有安装该工具,可以通过yum来安装使用 [root@localhost ~]# rpm -qa |grep dump [root@localhost ...
- git添加Github、Gitee、Gitlab秘钥
傻逼兮兮的我以为这三个的秘钥都是通用的 参考原文:https://www.cnblogs.com/zmdComeOn/p/11748991.html 首先确认已安装Git,可以通过 git –vers ...
- Token过期处理
Token用于进行接口鉴权,但是Token具有由后端设置的过期时间,当Token过期以后,就无法再请求数据了 项目中后端设置的过期时间为24h,测试时我们可以手动修改token值让Token失效 处理 ...
- STM32F103 的 USART5使用
STM32F103zet6 的串口5是UART5 不是 USART5
- python菜鸟学习: 6. 字典常用方法
# -*- coding: utf-8 -*-dict1 = {"name": "liyuzhoupan", "age": "22 ...
- shell语法2-默认变量、数组
一:文件参数变量 1.在执行shell脚本时,可以向脚本传递参数.$1是第一个参数,$2是第二个参数,以此类推.特殊的,$0是文件名(包含路径) #! /bin/bashecho "文件名: ...
- iClock数据服务器默认账号密码
网络空间资产搜索: shodan 搜索 默认密码 admin/a***n End!!!
- Python跳一跳小游戏
一:准备工具 adb 驱动 下载链接:http://adbshell.com/upload/adb.zip 安卓手机 打开手机调试模式 usb线接好手机和电脑 PyCharm:专门用于Python ...