定义:确保某个类只有一个实例,并且自行实例化且向所有类提供这个实例。
单例模式有六种常用的创建方式:
1.懒汉式(线程不安全)
在单线程下,用懒汉式已经足够好了,但是一旦遇到多线程,就有可能出现多个实例。
2.懒汉式(线程安全)
在并发较低的情况下,该方案也可以使用,但是一旦并发较高,线程锁带来的时间消耗将变得不可接受,于是我们有了双重检查锁写法。
3.饿汉式
在一开始就获得一个实例,由于不知道什么时候会使用,所以这种方法会比较浪费资源。
4.双重检查/双重校验锁
双重检查锁在相当长的一段时间内迷惑了所有人,他的一些问题直到后来才被发现——即编译器对语句优化后,其真实的执行顺序可能和期望的执行顺序不同,用new申请一片内存,他有可能会先申请内存,然后返回给指针,最后再执行构造函数,这样的话,当它在执行构造函数之前,如果有新的线程来尝试获取这个实例,由于静态实例的指针已不为空,就会直接返回给这个线程这片为初始化内存的地址。当然后来事情解决了,Java等语言添加了volatile关键字,C++也可以使用atomic头文件来保证实际执行顺序和期望顺序一致。
5.登记式/静态内部类
6.枚举
UML类图:
C++实现:
//1.懒汉式(线程不安全)
class SingleObject1
{
private:
SingleObject1() {}
static SingleObject1* Instance;
~SingleObject1() { delete Instance; }
public:
static SingleObject1* getInstance()
{
if (Instance == nullptr)
Instance = new SingleObject1();
return Instance;
}
};
//2.懒汉式(线程安全)
class SingleObject2
{
private:
SingleObject2() {}
static SingleObject2* Instance;
~SingleObject2() { delete Instance; }
static mutex mt;
public:
static SingleObject2* getInstance()
{
mt.lock();
if (Instance == nullptr)
Instance = new SingleObject2();
mt.unlock();
return Instance;
}
};
//3.饿汉式
class SingleObject3
{
private:
SingleObject3(){}
static SingleObject3* Instance;
~SingleObject3() { delete Instance; }
public:
static SingleObject3* getInstance()
{
return Instance;
}
};
SingleObject3* SingleObject3::Instance = new SingleObject3();
//4.双重检查/双重检验锁
class SingleObject4
{
private:
SingleObject4() {}
static atomic<SingleObject4*> Instance;
~SingleObject4() { delete Instance; }
static mutex mt;
public:
static SingleObject4* getInstance()
{
SingleObject4* tmp = Instance.load(std::memory_order_relaxed);
atomic_thread_fence(std::memory_order_acquire);
if (tmp == nullptr)
{
lock_guard<mutex>lock(mt);
tmp = Instance.load(memory_order_relaxed);
if (tmp == nullptr)
{
tmp = new SingleObject4();
atomic_thread_fence(std::memory_order_release);
Instance.store(tmp, std::memory_order_relaxed);
}
mt.unlock();
}
return tmp;
}
};
//5.登记式/静态内部类
class SingleObject5
{
private:
SingleObject5() {}
static class SingleObjectHolder
{
static SingleObject5* Instance;
public:
static SingleObject5* getInstanceOrg()
{
return Instance;
}
};
public:
static SingleObject5* getInstance()
{
return SingleObjectHolder::getInstanceOrg();
}
};
SingleObject5* SingleObject5::SingleObjectHolder::Instance= new SingleObject5();
//6.枚举
C++实现不了,见下面的C#中用Java代码代替的部分,如果有大佬能够用C++实现的希望能告知一下
C#实现:
//1.懒汉式(线程不安全)
public class SingleObject1
{
private static SingleObject1 Instance;
private SingleObject1() { }
public static SingleObject1 getInstance()
{
if (Instance == null)
Instance = new SingleObject1();
return Instance;
}
}
//2.懒汉式(线程安全)
public class SingleObject2
{
private static SingleObject2 Instance=null;
private static readonly object padlock = new object();
private SingleObject2() { }
public static SingleObject2 getInstance()
{
lock (padlock)
{
if (Instance == null)
Instance = new SingleObject2();
}
return Instance;
}
}
//3.饿汉式
public class SingleObject3
{
private static SingleObject3 instance = new SingleObject3();
public int count = 0;
private SingleObject3() { }
public static SingleObject3 getInstance()
{
return instance;
}
public void showMessage()
{
WriteLine("make yourself");
}
}
//4.双重检查/双重校验锁
public class SingleObject4
{
private static SingleObject4 Instance = null;
private static readonly object padlock = new object();
private SingleObject4() { }
public static SingleObject4 getInstance()
{
if(Instance==null)
lock (padlock)
{
if (Instance == null)
Instance = new SingleObject4();
}
return Instance;
}
}
//5.登记式/静态内部类
public class SingleObject5
{
private static class SingleObjectHolder
{
private static readonly SingleObject5 Instance =new SingleObject5();
public static SingleObject5 INSTANCE
{
get { return Instance; }
}
}
private SingleObject5() { }
public static SingleObject5 getInstance()
{
return SingleObjectHolder.INSTANCE;
}
}
//6.枚举(C#的枚举特性不支持以下写法,所以用Java代替)
public enum SingleObject6
{
INSTANCE,
public void whateverMethod() { };
}