设计模式go语言实现----单例模式Singleton

xiaoxiao2025-10-27  5

1 单例模式定义

保证一个类仅有一个实例,并提供一个访问它的全局访问点

使用单例模式需要注意三个要点:

某个类只能有一个实例这个类必须自行创建这个实例这个类必须自行向整个系统提供这个实例

单例模式写法:

饿汉式:类在*编译时*创建自己的实例懒汉式:类在*运行时*创建自己的实例

依据以上,读者可以自行辨别下面的代码属于哪种写法

2 单例模式的gol语言实现

2.1 不考虑并发情况

package manager import ( "fmt" ) var m *Manager func GetInstance() *Manager { if m == nil { m = &Manager{} } return m } type Manager struct { } func (p Manager) Manage() { fmt.Println("manage...") }

以上代码虽然实现了单例模式,在非并发的环境下执行,确实没有问题,但是考虑并发的情况,当第一个goroutine执行到m=&Manager{}之前,第二个gotoutine也来获取实例了,第二个gotoutine去判断m是不是等于nil,因为m=&Manager{}还没来得及执行,所以m=nil,那么if中的m = &Manager{}就可能会被执行两遍。 利用go的锁机制sync.Mutex修改以上代码。

2.2 考虑并发的情况

package manager import ( "fmt" "sync" ) var m *Manager var lock *sync.Mutex = &sync.Mutex{} func GetInstance() *Manager { lock.Lock() defer lock.Unlock() if m == nil { m = &Manager{} } return m } type Manager struct { } func (p Manager) Manage() { fmt.Println("manage...") }

这样修改之后,保证只有一个goroutine能够执行GetInstance函数,这样并发的问题就解决了,但是现在又有一个问题,每次goroutine来的时候都会被锁挡在GetInstance之外等上一个goroutine执行结束,这样代码执行效率肯定会下降,下面我们引入双重锁机制类修改我们的代码。

package manager import ( "fmt" "sync" ) var m *Manager var lock *sync.Mutex = &sync.Mutex{} func GetInstance() *Manager { if m == nil { lock.Lock() defer lock.Unlock() if m == nil { m = &Manager{} } } return m } type Manager struct { } func (p Manager) Manage() { fmt.Println("manage...") }

这样的话就避免了每次gouroutine过来的时候都需要加锁了。有的读者可能会问,为什么我们的代码里面需要执行两次m==nil的判断呢?试想一下当两个goroutine同时通过第一重m==nil判断的时候,由于锁机制,只有一个goroutine继续执行,另一个则在外排队等待,当第一个goroutine执行完毕之后,如果没有第二重m==nil判断的话,第二个goroutine也会继续执行语句m = &Manager{},这样就没有起到单例的目的了。 其实go语言中有一种机制可以保证代码只会被执行一次,而不需要我们手动加锁解锁,也就是go中的sync.Once,它的Do方法会保证传给它的函数只会被调用一次。

2.3 使用sync.Once改进

package manager import ( "fmt" "sync" ) var m *Manager var once sync.Once func GetInstance() *Manager { once.Do(func() { m = &Manager{} }) return m } type Manager struct { } func (p Manager) Manage() { fmt.Println("manage...") }

有没有发现go代码很优雅的就实现了单例模式呢?

参考资料: [1] 单例模式 [2] Go设计模式之单例模式 [3] 设计模式-单例模式(Go语言描述)

转载请注明原文地址: https://www.6miu.com/read-5038617.html

最新回复(0)