单例模式-Golang实现

2023-10-27

非线程安全的懒汉模式

main.go

package simple

import (
	"fmt"
	"sync"
	"time"
)

var singleton *Singleton

type Singleton struct {
}

func getInstance(wg *sync.WaitGroup) *Singleton {
	defer wg.Done()
	if nil == singleton {
		fmt.Println("init ")
		time.Sleep(time.Second)
		singleton = &Singleton{}
	}
	return singleton
}

simple_test.go

package simple

import (
	"sync"
	"testing"
)

var (
	wg sync.WaitGroup
)

func TestSimple(t *testing.T) {
	for i := 0; i < 30; i++ {
		wg.Add(1)
		go getInstance(&wg)
	}
	wg.Done()
}

image-20220105202604177

线程安全的懒汉模式

使用sync.Mutex 互斥锁实现

main.go

package main

import (
	"sync"
)

var wg sync.WaitGroup

func main() {
	for i := 0; i < 30; i++ {
		wg.Add(1)
		go getInstance()
	}
	wg.Wait()
}

single.go

package main

import (
	"fmt"
	"sync"
	"time"
)

type Singleton struct {
}

var (
	mu       sync.Mutex
	instance *Singleton
)

func getInstance() *Singleton {
	defer wg.Done()
	if nil == instance {
		mu.Lock()
		defer mu.Unlock()
		if nil == instance {
			fmt.Println("init")
			time.Sleep(time.Second)
			instance = &Singleton{}
		}
	}
	return instance
}

使用sync.Once实现

single.go

package main

import (
	"fmt"
	"sync"
	"time"
)

type single struct{}

var instance *single
var once sync.Once

func getInstance(wg *sync.WaitGroup) *single {
	defer wg.Done()
	once.Do(func() {
		fmt.Println("初始化了")
		time.Sleep(time.Second)
		instance = &single{}
	})
	return instance
}

single_test.go

package main

import (
	"sync"
	"testing"
)

var wg sync.WaitGroup

func TestSingleton(t *testing.T) {
	for i := 0; i < 30; i++ {
		wg.Add(1)
		go getInstance(&wg)
	}
	wg.Wait()
}

sync.Once源码

package sync

import (
	"sync/atomic"
)

type Once struct {
	done uint32
	m    Mutex
}

func (o *Once) Do(f func()) {
	if atomic.LoadUint32(&o.done) == 0 {
		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()
	}
}

由于互斥锁的开销较大,sync.Once利用sync/atomic包下的原子操作函数检测标志位来降低互斥锁的使用次数来提高性能

饿汉模式

hungry_test.go

package hungry

import (
	"fmt"
	"testing"
)

func TestHungry(t *testing.T) {
	s := GetInstance()
	fmt.Println(s)
}

single.go

package hungry

type singleton struct {
}

var instance *singleton = &singleton{}

func GetInstance() *singleton {
	return instance
}

比较懒汉模式和饿汉模式

懒汉模式就是在有调用的情况下才会去做初始化,若无调用就不做初始化

饿汉模式一般在程序加载起来的时候就要做初始化,无论是否调用

懒汉模式为了保证不重复创建实例,需要判空,然而所做的判空在并发情况下会同时通过判空条件,重复创建实例。所以说懒汉模式存在线程安全问题

问题就是可能会有多个线程同时进入创建实例的代码部分, 所以程序要做保证创建实例部分代码的原子性

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

单例模式-Golang实现 的相关文章

  • 离散仿真引擎基础作业与练习

    作业内容 一 简答题 1 解释 GameObjects 和 Assets 的区别与联系 2 下载几个游戏案例 分别总结资源 对象组织的结构 3 使用 debug 验证 MonoBehaviour 基本行为或事件触发条件 4 了解 GameO
  • Java设计模式:装饰者模式(Decorator Pattern)

    装饰者模式 涉及的重要设计原则 类应该对扩展开放 对修改关闭 装饰者模式定义 装饰者模式动态地将责任附加到对象上 若要扩展功能 装饰者提供了比继承更有弹性的替代方案 UML类图 装饰者模式事例 咖啡店 咖啡种类 1 深焙咖啡 DarkRoa
  • 简单工厂模式

    简单工厂模式 一 概念 从设计模式的类型上来说 简单工厂模式是属于创建型模式 又叫做静态工厂方法 StaticFactory Method 模式 但不属于23种GOF设计模式之一 简单工厂模式是由一个工厂对象决定创建出哪一种产品类的实例 简
  • C++设计模式-State状态模式

    State状态模式作用 当一个对象的内在状态改变时允许改变其行为 这个对象看起来像是改变了其类 UML图如下 State类 抽象状态类 定义一个接口以封装与Context的一个特定状态相关的行为 ConcreteState类 具体状态 每一
  • 六大设计原则--开闭原则

    定义 software entities like classes modules and functions should be open for extension but closed for modifications 一个软件实体
  • 程杰“大话设计模式”中的设计原则

    单一职责原则 SRP 就一个类而言 应该仅有一个引起它变化的原因 如果一个类承担的职责过多 就等于把这些职责耦合在了一起 一个职责的变化可能会削弱或者抑制这个类完成其他职责的能力 这种耦合会导致脆弱的设计 当发生变化时 设计会遭受到意想不到
  • 通过wireshark抓取telnet登陆密码

    笔者学校有一台设备 ip地址是 192 168 84 10 先打开wireshark捕获无线网卡 使用telnet登陆如图所示 按下回车 笔者这里输入的密码是 A603 现在回到wireshark停止抓包 并且在filter处输入如下的过滤
  • 详解原码、反码、补码——深入理解补码

    学过计算机原理的人都知道原码 反码 补码 但是有多少人知道为什么会有这三种码呢 这三种码又是用来干嘛的呢 众所周知 在计算机的世界只有01 那么显然所有的数都得转成二进制 这样计算机才能够理解 如何将一个十进制的数转成二进制就不说了 说下原
  • 设计模式(5)-适配器模式(Adapter Pattern)

    适配器模式 Adapter Pattern 顾名思义 就像变压器 转接头差不多 就像美国的生活电压是110V 中国是220V 就需要一个变压器将220V转换成110V 或者一个Type C接口想插如USB接口的东西 你就需要一个转换器 而这
  • 设计模式-2--工厂模式(Factory Pattern)

    一 什么是工厂模式 工厂模式 Factory Pattern 是一种创建型设计模式 它提供了一种创建对象的接口 但是将对象的实例化过程推迟到子类中 工厂模式允许通过调用一个共同的接口方法来创建不同类型的对象 而无需暴露对象的实例化逻辑 工厂
  • 分享几个项目中用到的设计模式

    前言 之前项目中出于扩展性和有雅性的考虑 使用了多种设计模式进行项目框架的设计 主要的一些设计模式是单例模式 工厂模式 策略模式 责任链模式 代理模式这几种 现在依次讲讲这几个的主要是实现方式和在我们项目中的应用场景 核心设计模式分享 单例
  • 【编译原理】 CS143 斯坦福大学公开课 第一周:简介

    youtube 1 1 Introduction to Compilers and interpreters 1 1 Introduction to Compilers and interpreters 编译器解释器介绍 两种主要的实现编程
  • HeadFirst 设计模式学习笔记10——MVC分析

    1 M V C Model View Controller 模式 视图 控制器 这是一种范型 模型对象正是应用系统存在的理由 你设计的对象 包含了数据 逻辑和其他在你的应用领域创建定制的类 视图通常是控件 用来显示和编辑 控制器位于二者中间
  • [设计模式]模板方法模式(Template Method)

    1 意图 定义一个操作中的算法的骨架 而将一些步骤延迟到子类中 TemplateMethod使得子类可以不改变一个算法的结构即可重定义该算法的某些特定步骤 2 动机 其实就是如意图所描述的 算法的骨架是一样的 就是有些特殊步骤不一样 就可以
  • 哈工大2020软件构造Lab3实验报告

    本项目于4 21日实验课验收 更新完成 如果有所参考 请点点关注 点点赞GitHub Follow一下谢谢 2020春计算机学院 软件构造 课程Lab3实验报告 Software Construction 2020 Spring Lab 3
  • JavaScript设计模式-02-单例模式

    Javascript 设计模式 02 单例模式 简介 单例就是保证一个类只有一个实例 实现的方法一般是先判断实例是否存在 如果存在直接返回 如果不存在就创建了再返回 确保了一个类只有一个实例对象 在JavaScript里 单例作为一个命名空
  • 设计模式详解---策略模式

    1 策略模式简介 策略模式 Strategy Pattern 是一种行为型设计模式 用于在运行时根据不同的情境选择不同的算法或策略 该模式将算法封装成独立的类 使得它们可以相互替换 而且可以独立于客户端使用它们的方式 1 1 主要角色 上下
  • 设计模式 原型模式 与 Spring 原型模式源码解析(包含Bean的创建过程)

    原创 疯狂的狮子Li 狮子领域 程序圈 2023 12 19 10 30 发表于辽宁 原型模式 原型模式 Prototype模式 是指 用原型实例指定创建对象的种类 并且通过拷贝这些原型 创建新的对象 原型模式是一种创建型设计模式 允许一个
  • C++设计模式 #3策略模式(Strategy Method)

    动机 在软件构建过程中 某些对象使用的的算法可能多种多样 经常改变 如果将这些算法都写在类中 会使得类变得异常复杂 而且有时候支持不频繁使用的算法也是性能负担 如何在运行时根据需求透明地更改对象的算法 将算法和对象本身解耦 从而避免上述问题
  • 【设计模式之美】理论一:怎么才算是单一原则、如何取舍单一原则

    文章目录 一 如何判断类的职责是否足够单一 二 类的职责是否设计得越单一越好 开始学习一些经典的设计原则 其中包括 SOLID KISS YAGNI DRY LOD 等 本文主要学习单一职责原则的相关内容 单一职责原则的定义 一个类只负责完

随机推荐

  • word图片撑满_word图片满页 word图片铺满整个页面

    word中如何让图片占满整个页面 确定 再确定 不OK了 7厘米 页面设置 里设置页面方向及纸张大小 当然也要根据你打印机性能 请将下面 锁定纵横比 那个钩取消 如将页面边距设置为0 点 版式 如图片太大你打印机不一定打印得了 再点右下角的
  • Python报错:IndexError: invalid index of a 0-dim tensor. Use `tensor.item()` in

    Python报错如下 E anaconda envs pytorch gpu python exe D project graphsage graphsage model py D project graphsage graphsage e
  • 自动找Bug/插件-代码静态检查findbugs-idea安装以及使用

    目录 简介 IDEA安装FindBugs Findbugs配置 配置排除一些类 扫描级别 IDEA中使用FindBugs 一些常见错误 补充 简介 Findbugs是一个静态分析工具 它检查类或者JAR 文件 将字节码与一组缺陷模式进行对比
  • 闲谈云计算

    其实一直到处看到关于云计算的东西和话题 云计算一直是一个很火的关键字 最近几天才有时间找来一本 云那些事 来看看 只是很粗略的看了关于云计算发展方向的一些问题 具体的云技术是一盘丰盛的大餐 得慢慢吃 其实我一直在没有认真去看云计算的时候 觉
  • Future和FutureTask用法详细介绍

    Future和FutureTask 文章目录 Future和FutureTask Future FutureTask Demo code output 在并发编程中 多线程的实现有继承Thread和Runnable 因为单继承的原因我们往往
  • Java阿里巴巴代码规范

    目录 1 编程规约 1 1 方法参数类型必须一致 不要出现自动装箱拆箱操作 1 1 1 反例 1 1 2 正例 1 2 SimpleDateFormat是线程不安全的 1 2 1 反例 1 2 2 正例 1 3 使用equals方法应该注意
  • 软件项目管理(第二版 宁涛)问答题(个人背诵)

    目录 第一章 概述 1 什么是软件项目管理 2 项目管理的 9 大知识领域是什么 3 项目管理的 5 个过程组是什么 5 项目经理的主要职责是什么 6 项目的特点是什么 7 项目和运营的共同点有哪些 8 项目集成管理是什么 9 规划过程组的
  • Flutter学习 — 从新页面返回数据给上一个页面

    效果图一 点击按钮 效果图二 点击YES后 返回上一级页面并传值 效果图三 收到值 并用底部弹出框显示结果 注释 代码 import package flutter material dart void main runApp new Ma
  • 关于Git的一点思考

    GIT历史 很多人都知道 Linus在1991年创建了开源的Linux 从此 Linux系统不断发展 已经成为最大的服务器系统软件了 Linus虽然创建了Linux 但Linux的壮大是靠全世界热心的志愿者参与的 这么多人在世界各地为Lin
  • YOLOV5之TensorRT模型部署

    目录 一 环境版本 1 1 概述 1 2 Ubuntu版本 1 3 python pytorch与tensorrt版本 1 4 cudnn版本 1 5 驱动版本 1 6 opencv版本 二 TensorRT与opencv环境安装 2 1
  • 虚拟化概念详解

    虚拟化的定义 虚拟化技术可以认为是一种对物理资源抽象化 进而形成虚拟化的版本的技术 虚拟化的目的 物理资源组成庞大的资源池 然后可以按需分配 随意切割物理资源 虚拟化资源分类 服务器虚拟化 服务器虚拟化就是将虚拟化技术应用于服务器 将一台服
  • 【STM32标准库】【基础知识】ADC转换,非DMA的单通道和多通道

    文章目录 ADC概述 ADC初始化 GPIO初始化 时钟 全局ADC设置 定义结构体 是否使用DMA 工作模式 分频 采样延迟 例程 单独ADC设置 定义结构体 连续转换 数据对齐 外部触发 通道数量 分辨率 扫描模式 例程 设置规则 打开
  • 【Git】(五)切换分支

    1 切换分支 git checkout newBranch 2 如果需要保留本地修改 git status git add git commit amend git checkout newBranch 3 强制切换分支 放弃本地修改 强制
  • vgg16-pytorch

    基于pytorch实现VGG16模型 刚听完土哥的入门pytorch 试着写一个不完善的vgg16 VGG16具体的架构 VGG16模型构建 卷积池化后尺寸计算公式 引入库 from torch import nn from torch n
  • 深入理解java虚拟机(十) Java 虚拟机运行时栈帧结构

    运行时栈帧结构 栈帧 Stack Frame 是用于虚拟机执行时方法调用和方法执行时的数据结构 它是虚拟栈数据区的组成元素 每一个方法从调用到方法返回都对应着一个栈帧入栈出栈的过程 每一个栈帧在编译程序代码的时候所需要多大的局部变量表 多深
  • <5>STM32库函文件分析-库函数

    使用STM32F10x的库函数文件编程就要对它的库文件有一个相对清晰的认识 即使不能做到知根知底 但当要使用到MCU的某个功能时 要知道相应的库函数在哪个对应的 h和 c 文件中 看懂并了解它的寄存器 下面我写一下我对其的认知 有错误的地方
  • SQLMAP工具 详细使用方法

    文章目录 SQLMAP简介 SQLMAP支持的注入模式 SQLMAP支持的数据库 SQLMAP安装 Linux Windows 更新 SQLMAP参数详解 使用 Options Target Reques Optimization Inje
  • UnityShader入门精要——透明物体阴影

    透明度测试 Shader Unity Shaders Book Chapter 9 Alpha Test With Shadow Properties Color Color Tint Color 1 1 1 1 MainTex Main
  • 2023最新软件测试面试题(带答案)

    1 请自我介绍一下 需简单清楚的表述自已的基本情况 在这过程中要展现出自信 对工作有激情 上进 好学 面试官您好 我叫 今年26岁 来自江西九江 就读专业是电子商务 毕业后就来深圳工作 有三年的软件测试工程师的经验 我性格比较开朗 能和同事
  • 单例模式-Golang实现

    目录 非线程安全的懒汉模式 线程安全的懒汉模式 使用sync Mutex 互斥锁实现 使用sync Once实现 饿汉模式 比较懒汉模式和饿汉模式 非线程安全的懒汉模式 main go package simple import fmt s