signal.cpp 3.3 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495
  1. //单例模式,也带点过度设计的无聊美感
  2. //单例模式是一种强制性的约束,一个物体全局只有唯一实例
  3. //在C/cpp中完全可以用全局变量实现(C++允许在函数外构建对象实例)
  4. //当然java就比较麻烦了,java不允许出现全局变量,单例模式似乎是唯一选择
  5. //单例模式的核心是C系语言静态变量的特性
  6. //所有的静态变量的生命周期都是全局的
  7. //C系语言中有三种静态变量,分别是类作用域,局部作用域和全局作用域
  8. //类作用域的静态变量所有的实例中只有唯一的副本,并且在访问的时候访问的是唯一的静态变量
  9. //局部作用域的静态变量,作用域只有局部,但是生命周期是全局(由于不进行链接,因此不会创建额外的副本)
  10. //全局静态变量的作用域是全局,但是只有内部链接性,即每一个包含头文件的的cpp文件中有一个独立的副本
  11. #include<atomic>
  12. #include<mutex>
  13. #include<thread>
  14. #include<iostream>
  15. //这个单例模式是内存安全的,在于cpp11之后现代cpp的static变量的构建是内存安全的
  16. class signal
  17. {
  18. protected:
  19. signal()=default;
  20. signal(const signal&)=delete;
  21. signal(signal&&)=delete;
  22. signal& operator=(const signal&)=delete;
  23. signal& operator=(signal&&)=delete;
  24. public:
  25. static signal& get() //核心是引用返回的是内部构建的局部变量而不是一个copy后的副本
  26. {
  27. static signal data;
  28. return data;
  29. }
  30. };
  31. //懒汉式,以及cpp11之前的单例模式
  32. //使用双检锁保证初始化顺序
  33. class thread_signal
  34. {
  35. private:
  36. //C++11之前没有这些类就需要使用boost实现
  37. static std::atomic<thread_signal*> instance;
  38. static std::mutex mtx;
  39. public:
  40. static thread_signal* get()
  41. {
  42. thread_signal* data=instance.load(std::memory_order_acquire);
  43. if(data==nullptr)
  44. {
  45. std::lock_guard<std::mutex> lock(mtx);
  46. data=instance.load(std::memory_order_relaxed); //重新加载一次防止在前面的判断过程中已经被改变,由于在锁的范围,直接用宽松内存序就好
  47. if(data==nullptr)
  48. {
  49. data=new thread_signal();
  50. instance.store(data,std::memory_order_relaxed);
  51. }
  52. }
  53. return data; //由于初始化是唯一的因此只会初始化一次,不会出现改变
  54. }
  55. };
  56. //每线程单例
  57. class signal_thread_local
  58. {
  59. protected:
  60. signal_thread_local(int _i):i(_i){};
  61. signal_thread_local(const signal_thread_local&)=delete;
  62. signal_thread_local(signal_thread_local&&)=delete;
  63. signal_thread_local& operator=(const signal_thread_local&)=delete;
  64. signal_thread_local& operator=(signal_thread_local&&)=delete;
  65. public:
  66. int i;
  67. static signal_thread_local& get() //核心是引用返回的是内部构建的局部变量而不是一个copy后的副本
  68. {
  69. thread_local signal_thread_local data(0); //构建线程作用域的单例
  70. return data;
  71. }
  72. };
  73. void fun(int j)
  74. {
  75. signal_thread_local& re1=signal_thread_local::get();
  76. re1.i=re1.i+j;
  77. signal_thread_local& re2=signal_thread_local::get();
  78. std::cout<<re2.i<<std::endl;
  79. }
  80. int main()
  81. {
  82. auto i1=std::thread(fun,1);
  83. auto i2=std::thread(fun,2);
  84. i1.join();
  85. i2.join();
  86. }