文章目录
- 懒汉式实现会延迟实例的创建,直到首次调用时才会实例化对象。为了保证并发安全,我们使用sync.Once来确保实例只被创建一次。 package main import ( “fmt” “sync” ) var wg sync.WaitGroup // Singleton 结构体定义 type Singleton struct{} var instance *Singleton var once sync.Once // GetInstance 返回全局唯一的实例 func GetInstance() *Singleton { once.Do(func() { instance = &Singleton{} }) return instance } func main() { // 获取单例实例并打印内存地址 for i := 0; i < 10; i++ { wg.Add(1) go func(index int) { defer wg.Done() s1 := GetInstance() fmt.Printf(“index %d, memory address: %pn”, index, s1) }(i) } wg.Wait() } 解析: sync.Once:确保传入的函数只执行一次,适用于懒加载单例实例。 once.Do:确保实例的创建操作只执行一次,且线程安全。
- 双重检查锁定通过两次检查实例状态,减少了加锁的开销,提高了性能。 package main import ( “fmt” “sync” ) var wg sync.WaitGroup // Singleton 结构体定义 type Singleton struct{} var instance *Singleton var lock sync.Mutex func GetInstance() *Singleton { if instance == nil { lock.Lock() defer lock.Unlock() if instance == nil { instance = &Singleton{} } } return instance } func main() { // 获取单例实例并打印内存地址 for i := 0; i < 10; i++ { wg.Add(1) go func(index int) { defer wg.Done() s1 := GetInstance() fmt.Printf(“index %d, memory address: %pn”, index, s1) }(i) } wg.Wait() } 解析: 双重检查:第一次无锁检查避免不必要的加锁开销,第二次加锁检查确保实例安全创建。 锁优化:仅在实例尚未创建时加锁,提高了性能。
- 利用sync/atomic包提供的原子操作,确保单例的线程安全。 package main import ( “fmt” “sync” “sync/atomic” “unsafe” ) var wg sync.WaitGroup // Singleton 结构体定义 type Singleton struct{} var instance unsafe.Pointer func GetInstance() *Singleton { // 使用原子操作获取实例 if atomic.LoadPointer(&instance) == nil { newInstance := &Singleton{} atomic.StorePointer(&instance, unsafe.Pointer(newInstance)) } return (*Singleton)(atomic.LoadPointer(&instance)) } func main() { // 获取单例实例并打印内存地址 for i := 0; i < 10; i++ { wg.Add(1) go func(index int) { defer wg.Done() s1 := GetInstance() fmt.Printf(“index %d, memory address: %pn”, index, s1) }(i) } wg.Wait() } 解析: unsafe.Pointer:用于直接处理内存地址,绕过类型系统。 atomic.LoadPointer和atomic.StorePointer:原子加载和存储指针,确保线程安全。
目录
- 单例模式的基本定义
- Go语言中的单例模式实现
- 1. 线程安全的懒汉式单例
- 2. 双重检查锁定(DCL)
- 3. 原子操作法
- 总结
单例模式(Singleton Pattern)是一种创建型设计模式,其核心思想在于确保一个类仅有一个实例,并提供一个全局访问点。该模式广泛应用于需要严格控制对象数量的场景,诸如数据库连接池、日志管理器、配置管理器等。
在Go语言中,实现单例模式有多种方法,以下介绍几种常见且线程安全的实现方式:
懒汉式实现会延迟实例的创建,直到首次调用时才会实例化对象。为了保证并发安全,我们使用sync.Once来确保实例只被创建一次。
package main
import (
"fmt"
"sync"
)
var wg sync.WaitGroup
// Singleton 结构体定义
type Singleton struct{}
var instance *Singleton
var once sync.Once
// GetInstance 返回全局唯一的实例
func GetInstance() *Singleton {
once.Do(func() {
instance = &Singleton{}
})
return instance
}
func main() {
// 获取单例实例并打印内存地址
for i := 0; i < 10; i++ {
wg.Add(1)
go func(index int) {
defer wg.Done()
s1 := GetInstance()
fmt.Printf("index %d, memory address: %pn", index, s1)
}(i)
}
wg.Wait()
}
解析:
sync.Once:确保传入的函数只执行一次,适用于懒加载单例实例。once.Do:确保实例的创建操作只执行一次,且线程安全。
双重检查锁定通过两次检查实例状态,减少了加锁的开销,提高了性能。
package main
import (
"fmt"
"sync"
)
var wg sync.WaitGroup
// Singleton 结构体定义
type Singleton struct{}
var instance *Singleton
var lock sync.Mutex
func GetInstance() *Singleton {
if instance == nil {
lock.Lock()
defer lock.Unlock()
if instance == nil {
instance = &Singleton{}
}
}
return instance
}
func main() {
// 获取单例实例并打印内存地址
for i := 0; i < 10; i++ {
wg.Add(1)
go func(index int) {
defer wg.Done()
s1 := GetInstance()
fmt.Printf("index %d, memory address: %pn", index, s1)
}(i)
}
wg.Wait()
}
解析:
- 双重检查:第一次无锁检查避免不必要的加锁开销,第二次加锁检查确保实例安全创建。
- 锁优化:仅在实例尚未创建时加锁,提高了性能。
利用sync/atomic包提供的原子操作,确保单例的线程安全。
package main
import (
"fmt"
"sync"
"sync/atomic"
"unsafe"
)
var wg sync.WaitGroup
// Singleton 结构体定义
type Singleton struct{}
var instance unsafe.Pointer
func GetInstance() *Singleton {
// 使用原子操作获取实例
if atomic.LoadPointer(&instance) == nil {
newInstance := &Singleton{}
atomic.StorePointer(&instance, unsafe.Pointer(newInstance))
}
return (*Singleton)(atomic.LoadPointer(&instance))
}
func main() {
// 获取单例实例并打印内存地址
for i := 0; i < 10; i++ {
wg.Add(1)
go func(index int) {
defer wg.Done()
s1 := GetInstance()
fmt.Printf("index %d, memory address: %pn", index, s1)
}(i)
}
wg.Wait()
}
解析:
unsafe.Pointer:用于直接处理内存地址,绕过类型系统。atomic.LoadPointer和atomic.StorePointer:原子加载和存储指针,确保线程安全。
在Go语言中,实现单例模式有多种方法,包括使用sync.Once、双重检查锁定和原子操作法。每种方法都有其独特的优点和适用场景。选择哪种方法取决于具体需求,如性能要求、代码简洁性等。在实际应用中,可以根据具体场景权衡利弊,选择最合适的实现方式。
到此这篇关于Go语言实现单例模式的多种方法的文章就介绍到这了,更多相关Go语言 单例模式内容请搜索风君子博客以前的文章或继续浏览下面的相关文章希望大家以后多多支持风君子博客!
您可能感兴趣的文章:
- Go语言优雅实现单例模式的多种方式
- Go设计模式之单例模式图文详解
- Go设计模式之单例模式讲解和代码示例
- Go 常见设计模式之单例模式详解
- Go语言单例模式详解
- go sync.Once实现高效单例模式详解
- Golang设计模式之单例模式详细讲解
- Go单例模式与Once源码实现
- Go 语言单例模式示例详解
- 详解Go语言设计模式之单例模式