golang atomic load 性能_设计模式之Golang单例模式

973565033acc50405c1fba988fde2d5e.gif

今天给大家讲下什么是单例模式,以及在Go语言中如何用正确的姿势实现它。其实单例模式是一种在平时开发中经常用到的软件设计模式。在设计模式结构中,其核心是只包含一个被称为单例的特殊类。通过单例模式可以确保系统中一个类只有一个实例,且该实例容易被外界访问,从而方便对实例数量的控制并节约系统资源。

1. 懒汉模式

懒汉模式是平时软件开发中比较常见的,也是用的最多的一种,该模式的最大缺点就是非线程安全。什么是非线程安全呢,这里就不展开讲了,后续会单独拿一期来讲什么是线程安全和非线程安全。

懒汉模式代码示例如下:

// 定义单例的结构体type Singleton struct {}// 声明一个Singleton结构体指针的变量var singleton *Singleton// 获取单例的函数,返回Singleton结构体指针类型func GetSingleton() *Singleton {  // 如果为空,则创建单例  if singleton == nil {    singleton = &Singleton{}  }  return singleton}
2. 带普通锁的单例模式

上面讲的懒汉模式,其实是没有带锁的,也就是并发处理时会发生竞争,从而会导致程序出错退出。

普通锁可以解决并发处理带来的问题,这里说的普通锁其实是使用了Go的sync.Mutex,其缺点就是要人工维护锁的添加和释放,在有些时候对锁的使用不当的话,反而会带来不必要的性能消耗,事倍功半。 其工作原理类似于Linux内核的futex对象,具体实现原理这里就不详细展开讲来,sync.Mutex的原理后面也会单独用一期来讲。

带普通锁的单例模式示例代码如下:

// 定义单例的结构体type Singleton2 struct {}// 声明一个Singleton结构体指针的变量var instance *Singleton2// 声明普通锁变量,muvar mu sync.Mutex// 获取带锁的单例函数func GetInstance() *Singleton2 {  // 加锁  mu.Lock()  // 函数退出前解锁  defer mu.Unlock()  // 如果为空,则创建单例  if instance == nil {    instance = &Singleton2{}  }  return instance}
3. 比较优雅的单例模式

以上两钟单例模式都有缺点,不是那么完美,而Golang本身sync.Once库里就已经很好的实现了单例模式。

示例代码如下:

// 创建一个结构体type Manager struct {}// 声明两个全局变量,一个是Manager结构体指针,一个是用于单例等nocevar m *Managervar once sync.Once// 创建Manager单例函数func GetManage() *Manager {  // once.Do已经优雅的封装好了部分加锁的代码  once.Do(func() {    m = &Manager{}  })  return m}

简单来说,sync.Once表示只执行一次函数,要做到这点,需要有两个条件:

  • 计数器,统计函数执行的次数

  • 线程安全,保证在多个goroutine(并发)情况下,函数仍然只执行一次,这里面其实也涉及到锁

其中sync.Once实现的核心函数就是Do(),看一下Do函数的源码,如下:

// Once源码的数据结构type Once struct {   m    Mutex   done uint32}// Do函数实现func (o *Once) Do(f func()) {   if atomic.LoadUint32(&o.done) == 1 {      return   }   o.m.Lock()   defer o.m.Unlock()   if o.done == 0 {      defer atomic.StoreUint32(&o.done, 1)      f()   }}

根据以上的源码可以看到是定义了Once结构体,其中的done成员就是用于统计函数执行的次数的,m成员是锁,保障线程安全的。

Do方法也比较简单:

  1. 首先原子操作load函数执行次数,如果已经执行过了,就return

  2. 然后lock加锁

  3. 执行函数,原子操作store函数执行次数,赋值为1

  4. 解锁unlock

如果换做是我们来写的话,一般就会先直接加锁,然后再比较函数执行的次数,而这里的源码用了原子操作,这样可以提高性能。总的来说,一些标志位可以通过原子操作来表示,从而避免加锁,提高性能。

以上完整示例代码已归档到我的github,如有需要欢迎下载学习交流:https://github.com/Scoefield/gokeyboardman/tree/main/singletonmode

本期设计模式之Golang单例模式的介绍就到这里啦,感谢您的阅读,如有疑问或意见请及时反馈给我们。


上一篇文章:

Golang中的“包”

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/505299.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

计算机网络 --- 传输层

传输层概述 传输层是只有主机才有的层次(路由器没有),为应用层提供通信服务,使用网络层的服务 传输层的功能 传输层提供进程与进程之间的逻辑通信(网络层提供主机之间的逻辑通信)。复用和分用传输层对收…

手机相机里面的m_荣耀V30 PRO详细评测:Matrix Camera相机矩阵开启5G视频时代

【IT168 评测】随着手机摄像头的配置越来越高,手机上已经能实现不俗的拍照效果,甚至超越了数码相机(DC)成为了人们最常用的拍照工具。进入今年的下半年,随着5G的商用,手机厂商对于手机的摄像头功能优化已经不局限于拍照&#xff0…

计算机网络 --- 传输层UDP协议

UDP只在IP数据报服务之上增加了很少功能,即复用分用和差错检测功能。 UDP的主要特点 UDP是无连接的,减少开销和发送数据之前的时延。UDP使用最大努力交付,即不保证可靠交付。UDP是面向报文的,适合一次性传输少量数据的网络应用。…

怎么调整字段长短_【芝士蛋糕怎么总烤不熟呢?】

烘焙群一位同学发来图片问,不是说看蛋糕有没有烤熟,要用牙签检测吗?可我这个芝士蛋糕,怎么扎都会带出面糊,烤不熟怎么办?看到这个被扎成刺猬的舒芙蕾芝士,原谅Windy 不厚道的笑了。也是Windy 疏…

计算机网络 --- 传输层TCP协议

TCP协议的特点 TCP是面向连接(虚连接)的传输层协议。每一条TCP连接只能有两个端点,每一条TCP连接只能是点对点的。TCP提供可靠交付的服务,无差错、不丢失、不重复、按序到达。可靠有序,不丢不重。TCP提供全双工通信。…

java 委托_java 能不能自己写一个类叫 java.lang.System/String 正确答案

来自:一汪清水 | 责编:乐乐链接:blog.csdn.net/tang9140/article/details/42738433正文 最近学习了下java类加载相关的知识。然后看到网上有一道面试题是能不能自己写个类叫java.lang.System?网上提供的答案:通常不可…

中奖人js滚动效果_js使用transition效果实现无缝滚动

作者:李大雷出自:SegmentFault 思否原文:segmentfault.com/a/1190000023945464前言无缝轮播一直是面试的热门题目,而大部分答案都是复制第一张到最后。诚然,这种方法是非常标准,那么有没有另类一点的方法呢…

计算机网络 --- 应用层

应用层概述 应用层对应用程序的通信提供服务。 应用层协议定义: 应用进程交换的报文类型,请求还是响应各种报文类型的语法,如报文中的各个字段及其详细描述字段的语义,即包含在字段中的信息的含义进程何时,如何发送…

opencv机器学习线性回归_Python机器学习之?线性回归入门(二)

线性回归原理介绍文章目录机器学习分类线性回归原理线性回归定义线性回归背后矩阵运算机器学习分类机器学习的主要任务便是聚焦于两个问题:分类和回归分类相信大家都不会陌生,生活中会见到很多的应用,比如垃圾邮件识别、信用卡发放等等&#…

php 邮件发送是html 没样式_使用python发送邮件

发送邮件这个功能非常实用,比如你写了一个爬虫,可以通过邮件来接收程序异常或者任务完成的通知,再比如你搭了一个网站,别人只需留下他的邮箱,你就可以自动给他发送邮件。总之我觉得邮件通知非常适合那些处理批量、大量…

easypoi设置黑色边框_迷人的G-SHOCK MTG-B1000XBD,碳纤维与黑色金属的魅力

美国最大的奢侈腕表盛会,第五届纽约WatchTime于2019年10月25日至26日在曼哈顿中城的Gotham Hall举行,共有37个参展品牌展出了最新的腕表款式,卡西欧(Casio)在G-SHOCK高级系列MT-G中展示了最新作品“ MTG-B1000XBD”和“ MTG-B1000…

c语言 单词变复数_【热点】浅谈 :怎样学好C语言?

是新朋友吗?记得先点蓝字关注我哦~本文共 1900 字,预计阅读时间: 7 分钟。最近有好多朋友和我抱怨说C语言真的太难学了,你有没有什么好的意见?嗯,的确如此,我上个学期学C语言的时候也…

安川机器人报错代码_今日 IPO|对标库卡机器人的先惠技术上市 近八成收入靠上汽...

面对全球金融体系的重构,与中国资本市场的变革。「晚点」希望从小处入手,以每日 IPO 公司的快速报道,记录这个时代的变化。通过「晚点早知道」,我们希望可以让读者只需要花几分钟时间,就可以了解到当天上市公司里&…

htmlplay前端编辑器下载_2019年最好用的代码编辑器推荐

对于经常需要编写代码的程序员来说,拥有一款自己的编辑器是非常重要的事情,一款好用的代码编辑器往往能够让代码的编辑更加流畅,今天我们为大家带来最流行的代码编辑器Sublime TextSublime Text是一款快速轻量可定制的代码编辑器,…

geoserver发布瓦片_Geoserver2.15.1配置自带GeoWebCache 插件发布ArcGIS Server瓦片

之前写过一篇关于 Geoserver2.8.5 版本的部署配置发布 ArcGIS Server 瓦片点击查看,那是下载 Geoserver2.8.5 源码编译,重新打包 jar 来部署配置思路的,版本也比较旧。最近我想升级 Geoserver 版本,所以从官网下载最新版本 Geoser…

32 块大小_详解Linux文件系统的完整结构--引导块、超级块、GDT等

概述今天主要介绍一下Linux系统的文件系统,一起来看看吧~文件系统组成网上看到的一张完整的文件系统图,如下:首先,该图中有Boot Block、Super Block、GDT、Reserver GDT这几个概念,下面会分别介绍它们。然后&#xff0…

pythonista脚本_IPA Installer脚本下载-Pythonista脚本IPA Installer(安装手机ipa文件) - 极光下载站...

pythonista脚本IPA Installer,通过这个脚本,无需电脑,也可有让iOS苹果手机用户端轻松安装ipa文件,非常实用。安装速度快,没有大小限制。 主要特点: 无需上传,本地安装 没有大小限制 安装速度快 …

channelsftp 上传文件为空_SpringBoot文件上传下载篇(九)

点击上方蓝色字体,关注我们上传文件是互联网中应用的场景之一,最典型的情况就是上传头像。文件上传主要是将文件通过IO流传输到服务器的某一个特定的文件夹下。Why->MultipartFile?解析源码:public interface MultipartFile extends InputStreamSour…

excel 科学计数法转换成文本完整显示_表格技巧—Excel里身份证号码显示不全的多种解决办法...

运用Excel表格可以快速统计和汇总数据,那么当在表格当中输入身份证号码时,表格通常显示不完全,这是为什么呢,今天小编就来给大家详细介绍当身份证号码显示不全时的多种解决办法,一起来学习一下吧。首先,我们…