浅谈golang中的单例模式

来自一个大佬的博客,建议食用

设计模式不分语言,是一种思维层面的体现,但是不能在不同语言中使用同一套实现(每种语言有不同的特性),比如go,本身是没有继承一说,但是通过结构体的组合来实现语义上的继承。而多态也是通过接口的方式来实现的。

下方的图来自于大佬博客,贴在这里方便查看!!!

设计原则

在这里插入图片描述

设计模式

在这里插入图片描述

创建型模式

单例模式

分为懒汉式和饿汉式。

饿汉式

//饿汉式
type singleton struct {
}

var instance *singleton

//在go文件的加载顺序中,先加载init,后加载main
func init() {
	instance = &singleton{}
}

//获取实例
func GetInstance() *singleton {
	return instance
}

懒汉式

形式一: 使用once包保证只会调用一次

import "sync"

var (
	lazySingleton *singleton
	once          = &sync.Once{}
)

//懒汉式获取实例,双重检查
func GetLazyInstance() *singleton {
	once.Do(func() { //第二次检查,因为once只会调用一次
		lazySingleton = &singleton{}
	})

	return lazySingleton
}

形式二: 内部实现double check ,和once源码写的一样

type lock struct {
	mutex sync.Mutex
	done  uint32
}

var (
	l              = &lock{}
	lazySingleton2 *singleton
)

func GetLazyInstance2() *singleton {
	if atomic.LoadUint32(&l.done) == 0 {
		l.mutex.Lock()
		//这里有个小技巧,使用defer栈来做资源释放
		defer l.mutex.Unlock()
		if l.done == 0 {
			defer atomic.StoreUint32(&l.done, 1)
			lazySingleton2 = &singleton{}
		}
	}
	return lazySingleton2
}

除此之外

懒汉式中使用了double check,其实现逻辑是在once中体现。

type Once struct {
	done uint32   //用来配合原子更新
	m    Mutex	  //锁
}

func (o *Once) Do(f func()) {
	if atomic.LoadUint32(&o.done) == 0 {		//第一次check
		//直接调方法,进入加锁的一步
		o.doSlow(f)
	}
}

func (o *Once) doSlow(f func()) {
	o.m.Lock()                          // 加锁
	defer o.m.Unlock()					//return后解锁
	
	if o.done == 0 {                    //第二次check
		defer atomic.StoreUint32(&o.done, 1)	//return后原子更新
		f()								//执行你想要的逻辑
	}
}

疑问:
在once的双重检查中,修改once.done的值,源代码使用的是atomic进行赋值,但是我的理解是在临界区之中直接使用once.done = 1即可。
之后我在本地复刻了once,并且只修改了once.done这一行代码。同时开很多协程去执行,发现依然能履行once本身的意义。
那么问题来了,源代码里的原子赋值是否有意义呢?~跪求大佬告知

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值