|
@@ -0,0 +1,95 @@
|
|
|
+//单例模式,也带点过度设计的无聊美感
|
|
|
+//单例模式是一种强制性的约束,一个物体全局只有唯一实例
|
|
|
+//在C/cpp中完全可以用全局变量实现(C++允许在函数外构建对象实例)
|
|
|
+//当然java就比较麻烦了,java不允许出现全局变量,单例模式似乎是唯一选择
|
|
|
+
|
|
|
+
|
|
|
+//单例模式的核心是C系语言静态变量的特性
|
|
|
+//所有的静态变量的生命周期都是全局的
|
|
|
+//C系语言中有三种静态变量,分别是类作用域,局部作用域和全局作用域
|
|
|
+//类作用域的静态变量所有的实例中只有唯一的副本,并且在访问的时候访问的是唯一的静态变量
|
|
|
+//局部作用域的静态变量,作用域只有局部,但是生命周期是全局(由于不进行链接,因此不会创建额外的副本)
|
|
|
+//全局静态变量的作用域是全局,但是只有内部链接性,即每一个包含头文件的的cpp文件中有一个独立的副本
|
|
|
+#include<atomic>
|
|
|
+#include<mutex>
|
|
|
+#include<thread>
|
|
|
+#include<iostream>
|
|
|
+//这个单例模式是内存安全的,在于cpp11之后现代cpp的static变量的构建是内存安全的
|
|
|
+class signal
|
|
|
+{
|
|
|
+protected:
|
|
|
+ signal()=default;
|
|
|
+ signal(const signal&)=delete;
|
|
|
+ signal(signal&&)=delete;
|
|
|
+ signal& operator=(const signal&)=delete;
|
|
|
+ signal& operator=(signal&&)=delete;
|
|
|
+public:
|
|
|
+ static signal& get() //核心是引用返回的是内部构建的局部变量而不是一个copy后的副本
|
|
|
+ {
|
|
|
+ static signal data;
|
|
|
+ return data;
|
|
|
+ }
|
|
|
+};
|
|
|
+
|
|
|
+
|
|
|
+//懒汉式,以及cpp11之前的单例模式
|
|
|
+//使用双检锁保证初始化顺序
|
|
|
+class thread_signal
|
|
|
+{
|
|
|
+private:
|
|
|
+ //C++11之前没有这些类就需要使用boost实现
|
|
|
+ static std::atomic<thread_signal*> instance;
|
|
|
+ static std::mutex mtx;
|
|
|
+public:
|
|
|
+ static thread_signal* get()
|
|
|
+ {
|
|
|
+ thread_signal* data=instance.load(std::memory_order_acquire);
|
|
|
+ if(data==nullptr)
|
|
|
+ {
|
|
|
+ std::lock_guard<std::mutex> lock(mtx);
|
|
|
+ data=instance.load(std::memory_order_relaxed); //重新加载一次防止在前面的判断过程中已经被改变,由于在锁的范围,直接用宽松内存序就好
|
|
|
+ if(data==nullptr)
|
|
|
+ {
|
|
|
+ data=new thread_signal();
|
|
|
+ instance.store(data,std::memory_order_relaxed);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return data; //由于初始化是唯一的因此只会初始化一次,不会出现改变
|
|
|
+ }
|
|
|
+};
|
|
|
+
|
|
|
+
|
|
|
+//每线程单例
|
|
|
+class signal_thread_local
|
|
|
+{
|
|
|
+protected:
|
|
|
+ signal_thread_local(int _i):i(_i){};
|
|
|
+ signal_thread_local(const signal_thread_local&)=delete;
|
|
|
+ signal_thread_local(signal_thread_local&&)=delete;
|
|
|
+ signal_thread_local& operator=(const signal_thread_local&)=delete;
|
|
|
+ signal_thread_local& operator=(signal_thread_local&&)=delete;
|
|
|
+public:
|
|
|
+ int i;
|
|
|
+ static signal_thread_local& get() //核心是引用返回的是内部构建的局部变量而不是一个copy后的副本
|
|
|
+ {
|
|
|
+ thread_local signal_thread_local data(0); //构建线程作用域的单例
|
|
|
+ return data;
|
|
|
+ }
|
|
|
+};
|
|
|
+
|
|
|
+
|
|
|
+void fun(int j)
|
|
|
+{
|
|
|
+ signal_thread_local& re1=signal_thread_local::get();
|
|
|
+ re1.i=re1.i+j;
|
|
|
+ signal_thread_local& re2=signal_thread_local::get();
|
|
|
+ std::cout<<re2.i<<std::endl;
|
|
|
+}
|
|
|
+
|
|
|
+int main()
|
|
|
+{
|
|
|
+ auto i1=std::thread(fun,1);
|
|
|
+ auto i2=std::thread(fun,2);
|
|
|
+ i1.join();
|
|
|
+ i2.join();
|
|
|
+}
|