文章目录

  • GoLang使用sync.Once
    • 1.sync.Once介绍
    • 2.sync.Once使用实例
    • 3.sync.Once实现单例模式

注:本文基于Windos系统上Go SDK v1.8进行

GoLang使用sync.Once

1.sync.Once介绍

在某些场景下我们需要确保某些操作即使在高并发的场景下也只会被执行一次,例如只加载一次配置文件等。
Go语言中的sync包中提供了一个针对只执行一次场景的解决方案——sync.Once,sync.Once只有一个Do方法,其签名如下:
func (o *Once) Do(f func())
注意:如果要执行的函数f需要传递参数就需要搭配闭包来使用。

2.sync.Once使用实例

加载配置文件示例
延迟一个开销很大的初始化操作到真正用到它的时候再执行是一个很好的实践。因为预先初始化一个变量(比如在init函数中完成初始化)会增加程序的启动耗时,而且有可能实际执行过程中这个变量没有用上,那么这个初始化操作就不是必须要做的。我们来看一个例子:

var icons map[string]image.Imagefunc loadIcons() {icons = map[string]image.Image{"left":  loadIcon("left.png"),"up":    loadIcon("up.png"),"right": loadIcon("right.png"),"down":  loadIcon("down.png"),}
}// Icon 被多个goroutine调用时不是并发安全的
func Icon(name string) image.Image {if icons == nil {loadIcons()}return icons[name]
}

多个 goroutine 并发调用Icon函数时不是并发安全的,现代的编译器和CPU可能会在保证每个 goroutine 都满足串行一致的基础上自由地重排访问内存的顺序。loadIcons函数可能会被重排为以下结果:

func loadIcons() {icons = make(map[string]image.Image)icons["left"] = loadIcon("left.png")icons["up"] = loadIcon("up.png")icons["right"] = loadIcon("right.png")icons["down"] = loadIcon("down.png")
}

在这种情况下就会出现即使判断了icons不是nil也不意味着变量初始化完成了。考虑到这种情况,我们能想到的办法就是添加互斥锁,保证初始化icons的时候不会被其他的 goroutine 操作,但是这样做又会引发性能问题。
使用sync.Once改造的示例代码如下:

var icons map[string]image.Imagevar loadIconsOnce sync.Oncefunc loadIcons() {icons = map[string]image.Image{"left":  loadIcon("left.png"),"up":    loadIcon("up.png"),"right": loadIcon("right.png"),"down":  loadIcon("down.png"),}
}// Icon 是并发安全的
func Icon(name string) image.Image {loadIconsOnce.Do(loadIcons)return icons[name]
}

3.sync.Once实现单例模式

下面是借助sync.Once实现的并发安全的单例模式:
sync.Once其实内部包含一个互斥锁和一个布尔值,互斥锁保证布尔值和数据的安全,而布尔值用来记录初始化是否完成。这样设计就能保证初始化操作的时候是并发安全的并且初始化操作也不会被执行多次。

package singletonimport ("sync"
)type singleton struct {}var instance *singleton
var once sync.Oncefunc GetInstance() *singleton {once.Do(func() {instance = &singleton{}})return instance
}

GoLang使用sync.Once相关推荐

  1. 记一次golang中sync.Map并发创建、读取的问题

    记一次golang中sync.Map并发创建.读取的问题  cunfate https://www.jianshu.com/p/f472e79909bc 背景: 我们有一个用go做的项目,其中用到了z ...

  2. 深入Golang之sync.Pool详解

    转载地址:https://www.cnblogs.com/sunsky303/p/9706210.html 我们通常用golang来构建高并发场景下的应用,但是由于golang内建的GC机制会影响应用 ...

  3. 由浅入深聊聊Golang的sync.Map

    前言 今天在技术群中有小伙伴讨论并发安全的东西,其实之前就有写过map相关文章:由浅入深聊聊Golang的map.但是没有详细说明sync.Map是怎么一回事. 回想了一下,竟然脑中只剩下" ...

  4. golang的sync包例子

    package mainimport ("fmt""sync" )var wg sync.WaitGroupfunc asyncTestFunc() {for ...

  5. Golang学习 - sync 包

    ------------------------------------------------------------临时对象池Pool 用于存储临时对象,它将使用完毕的对象存入对象池中,在需要的时 ...

  6. Golang 中 sync/atomic 包的原子操作

    背景 Go中多协程的情况下, 要保证操作的原子性,一般要使用RWMutex或者Mutex, 但是锁使用起来比较复杂,还要考虑lock 和unlock 顺序和成对出现,不注意就容易出错. 于是在sync ...

  7. golang中的sync.WaitGroup

    golang中的sync.WaitGroup Posted on 2015/04/09刚才看golang的sync的包,看见一个很有用的功能.就是WaitGroup. 先说说WaitGroup的用途: ...

  8. Golang sync.Pool 简介与用法

    文章目录 1.简介 2.应用 2.1 标准库的应用 2.2 复用 bytes.Buffer 参考文章 1.简介 Pool 是可伸缩.并发安全的临时对象池,用来存放已经分配但暂时不用的临时对象,通过对象 ...

  9. Golang sync.WaitGroup 简介与用法

    1.简介 sync.WaitGroup 用于阻塞等待一组 Go 程的结束.主 Go 程调用 Add() 来设置等待的 Go 程数,然后该组中的每个 Go 程都需要在运行结束时调用 Done(), 递减 ...

  10. Golang sync.Mutex 与 sync.RWMutex

    文章目录 1.sync.Mutex 2.sync.RWMutex 2.1 Lock()与Unlock() 2.2 RLock() 和 RUnlock() 2.3 错误使用异常 参考文献 Golang ...

最新文章

  1. 第二节 数学基础与语言学基础
  2. 完整复现何恺明ICCV获奖论文结果并开源 !(附论文开源代码)
  3. Yii2多模型与事务的用法
  4. 揭秘硅谷进化历程:机遇无穷 成功需付出更高代价
  5. as3是js和java_AS3与JS进行交互(一)
  6. 怎么将matlab滤波器系数导出_matlab与FPGA数字信号处理系列(1)——通过matlab工具箱设计FIR数字滤波器...
  7. 在ASP.Net Core和JAVA中,使用Azure配置密钥——Key Vault
  8. DistBelief 框架下的并行随机梯度下降法 - Downpour SGD
  9. Docker容器技术-基础与架构
  10. php 特有,PHP特殊数据类型有哪些?原来这门编程语言如此有趣
  11. 1到10选一个数字读心术_虾米启示录:理想音乐生活与现实之间 隔着一个草莓蛋糕的距离...
  12. opencv 图像融合
  13. ZZCMS 2022版白盒审计
  14. php移除excel密码,excel保护密码忘记怎么撤销保护工作表
  15. 计算机开机主机不停地重启,电脑开机不断重启,可能是两个原因
  16. Uber 《Go语言编程规范》学习笔记(一)
  17. linux文件读取程序,Linux系统编程:文件的读取写入
  18. 查询rssi指令_h3c无线控制器常用命令(wx)
  19. Pwnginx – a nginx backdoor offering shell
  20. HarmonyOS实战—Text组件宽高三种值的写法和颜色属性

热门文章

  1. 【AAAA级LED护眼学习台灯照明方案】PWM内部转模拟,调光深度1%,无频闪顾虑,低亮无抖动LED恒流驱动芯片FP7102/FP7103/FP7208/FP7209
  2. linux服务器什么意思,linux中的“/”和“./”是什么意思
  3. IC Compiler指南——布图规划(一)
  4. Pm2 部署 Nuxt 项目
  5. 如何理解STM32单片机引脚的复用功能?
  6. 什么是对象存储?OSD架构及原理
  7. 【zhasite】托业英语阅读技巧有哪些
  8. 浙江新曙光建设_中习集团大厦项目工地与姜太公签约,正在使用太公管工进行实名制考勤...
  9. 小米怎么和计算机连接网络连接网络,小米电视如何与电脑连接
  10. Linux 克隆虚拟机引起的“Device eth0 does not seem to be present, delaying initialization”