1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495 |
- //单例模式,也带点过度设计的无聊美感
- //单例模式是一种强制性的约束,一个物体全局只有唯一实例
- //在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();
- }
|