单例设计模式 golang、java实现
这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式。
这种模式涉及到一个单一的类,该类负责创建自己的对象,同时确保只有单个对象被创建。这个类提供了一种访问其唯一的对象的方式,可以直接访问,不需要实例化该类的对象。
单例模式的要点有三个:
懒汉模式:
懒汉式一开始不会实例化,什么时候用就什么时候new,才进行实例化。
懒汉式一般使用都会加同步锁,效率比饿汉式差。
饿汉模式:
饿汉式在一开始类加载的时候就已经实例化,并且创建单例对象,以后只管用即可。
饿汉式没有加任何的锁,因此执行效率比较高。
这种方式是最基本的实现方式,这种实现最大的问题就是不支持多线程。因为没有加锁 synchronized,所以严格意义上它并不算单例模式。
这种方式 lazy loading 很明显,不要求线程安全,在多线程不能正常工作
java:
public class Singleton {
private static Singleton instance;
private Singleton (){}
public static Singleton getInstance() {
if (instance == null) {
instance = new Singleton();
}
return instance;
}
}
golang:
type singleton struct{}
var ins *singleton
func GetIns() *singleton{
if ins == nil {
ins = &singleton{}
}
return ins
}
这种方式具备很好的 lazy loading,能够在多线程中很好的工作,但是,效率很低,99% 情况下不需要同步。
优点:第一次调用才初始化,避免内存浪费。
缺点:必须加锁 synchronized 才能保证单例,但加锁会影响效率。
getInstance() 的性能对应用程序不是很关键(该方法使用不太频繁)。
java:
public class Singleton {
private static Singleton instance;
private Singleton (){}
public static synchronized Singleton getInstance() {
if (instance == null) {
instance = new Singleton();
}
return instance;
}
}
golang:
type singleton struct{}
var ins *singleton
var mu sync.Mutex
func GetIns() *singleton{
mu.Lock()
defer mu.Unlock()
if ins == nil {
ins = &singleton{}
}
return ins
}
这种方式比较常用,但容易产生垃圾对象。
优点:没有加锁,执行效率会提高。
缺点:类加载时就初始化,浪费内存。
java:
public class Singleton {
private static Singleton instance = new Singleton();
private Singleton (){
}
public static Singleton getInstance() {
return instance;
}
}
golang:
type singleton struct{}
var ins *singleton = &singleton{}
func GetIns() *singleton{
return ins
}
这种方式采用双锁机制,安全且在多线程情况下能保持高性能 lazy loading
getInstance() 的性能对应用程序很关键。
java:
public class Singleton {
private volatile static Singleton singleton;
private Singleton (){}
public static Singleton getSingleton() {
if (singleton == null) {
synchronized (Singleton.class) {
if (singleton == null) {
singleton = new Singleton();
}
}
}
return singleton;
}
}
golang:
type singleton struct{}
var ins *singleton
var mu sync.Mutex
func GetIns() *singleton{
if ins == nil {
mu.Lock()
defer mu.Unlock()
if ins == nil {
ins = &singleton{}
}
}
return ins
}
这种方式只限在Golang中。
1.使用atomic 原子操作计数器,用于记录此Once对象下的done的值,func()方法只执行一次
2.使用Mutex互斥锁保证多协程操作的安全性
不管成功还是失败只执行一次,慎用
golang:
type singleton struct{}
var ins *singleton
var once sync.Once
func GetIns() *singleton {
once.Do(func(){
ins = &singleton{}
})
return ins
}