单例模式是一种常用的软件设计模式。在它的核心结构中只包含一个被称为单例类的特殊类。通过单例模式可以保证系统中一个类只有一个实例而且该实例易于外界访问,从而方便对实例个数的控制并节约系统资源。如果希望在系统中某个类的对象只能存在一个,单例模式是最好的解决方案。
PHP实现:
<?php
class Singleton {
//保存类实例的静态成员变量
private static $_instance;
//private 构造函数
private function __construct() {
}
private function __clone() {
}
//单例方法访问类实例
public static function getInstance() {
if (!(self::$_instance instanceof self)) {
self::$_instance = new self();
}
return self::$_instance;
}
}
$instance = Singleton::getInstance();
将构造方法设为private从而防止直接new一个对象;将__clone方法设为private,防止通过clone复制一个对象;需要该类对象”只能”通过调用Singleton::getInstance()方法的方式,而getInstance方法通过”饿汉模式”保证类变量$_instance只会被初始化一次,即Singleton类只能有一个对象。
一般来说我们平时大多都这么写的,没太大问题,但是会有一些情况下通过反射创建对象,序列化反序列化后创建的对象,多线程创建的对象会破坏上述单例模式。详细请看这篇文章的分析http://blog.youkuaiyun.com/yesuhuangsi/article/details/52187875
golang实现:
package Singleton
type singleton struct {
}
var instance *singleton
func GetInstance() *singleton {
if instance == nil {
instance = &singleton{}
}
return instance
}
同样的饿汉模式实现单例,这在go里面同样非线程安全,不能在多线程中正常工作,我们可以给它带上线程锁:
package Singleton
import (
"sync"
)
type singleton struct {
}
var (
instance *singleton
mu sync.Mutex
)
func GetInstance() *singleton {
if instance == nil {
mu.Lock()
defer mu.Unlock()
if instance == nil{
instance = &singleton{}
}
}
return instance
}
sync.mutext是Go语言底层基础对象之一,用于构建多个goroutine间的同步逻辑,因此被大量高层对象所使用。
这是一个不错的方法,但是还并不是很完美。因为编译器优化没有检查实例存储状态。如果使用sync/atomic包的话 就可以自动帮我们加载和设置标记。
package Singleton
import (
"sync"
"sync/atomic"
)
type singleton struct {
}
var (
instance *singleton
mu sync.Mutex
initialized uint32
)
func GetInstance() *singleton {
if atomic.LoadUInt32(&initialized) == 1 {
return instance
}
mu.Lock()
defer mu.Unlock()
if initialized == 0 {
instance = &singleton{}
atomic.StoreUint32(&initialized, 1)
}
return instance
}
还有一种简洁的方式非常好
package singleton
import (
"sync"
)
type singleton struct {
}
var instance *singleton
var once sync.Once
func GetInstance() *singleton {
once.Do(func() {
instance = &singleton{}
})
return instance
}
利用了once.Do(f)只执行一次的特性。
参考了文章:https://xiequan.info/go%E7%9A%84%E5%8D%95%E4%BE%8B%E6%A8%A1%E5%BC%8F/