C++ Singleton單例實現方式
阿新 • • 發佈:2018-12-26
1.singleton模式的意圖是什麼?或者說使用singleton模式解決的問題是什麼?
答:保證一個類僅有一個例項,並提供一個訪問它的全域性訪問點,該例項被所有程式模組共享!!!
2.解決上述問題的方法:
方法一: 全域性變數或是靜態變數
此方法存在的問題:這樣做雖然能保證方便的訪問例項,但是不能保證只宣告一個物件——也就是說除了一個全域性例項外,仍然能建立此類的區域性例項。當然一不小心可能再建立另一個全域性的例項。
方法二:自己實現個簡單的單例(C++版本)。
答:亦可以防止防止做為基類使用呀!和 5 的作用豈不是重複了?
5.還有將解構函式宣告為private,這種設計我目前還不太理解是為什麼?
答:應該是防止被做為基類使用!(2017.02.22)
6.在使用多執行緒測試此段程式碼時,使用g++做編譯的命令格式是:
g++ -std=c++0x -Wl,--no-as-needed main.cpp -pthread -o test.out
main.cpp部分的程式碼如下:
2017年2月27日更新以下內容: 無鎖結構的實現方式,但是經試驗驗證,以現在程式碼的實現方式,耗時和有鎖結構相比無明顯區別: 這可能是因為獲得鎖之後的程式碼只需要瞬間的執行時間,從而沒有明顯因為等待鎖而導致程式碼耗時增加! 程式碼中的__sync_val_compare_and_swap(&m_flag_,0,1)
上述程式碼有三個點需要說明下: 1.多執行緒:為防止多執行緒情況下產生多個單例指標,所以需要新增g_mutex來實現加鎖和解鎖。 2.double-check:就是if(m_instance_==NULL) 做了兩次判斷,別的文章說如果不double-check會導致多個執行緒訪問get函式時導致過多執行緒掛起,這句話我的體會不深,理解不深刻,鸚鵡學舌了! 3.現在發現,這個單例模式沒有釋放類T的例項的操作!——貌似智慧指標auto_ptr能解決這個問題,或是新增Delete()函式,在某個適當的時候集中銷燬! 4.還有建構函式宣告為private能夠防止在singleton外隨意的例項化!#ifndef SINGLETON_H #define SINGLETON_H #include<stddef.h> #include<iostream> #include<mutex> using namespace std; namespace test { std::mutex g_mutex; template <typename T> class Singleton { public: static T* get() { if(m_instance_==NULL) { g_mutex.lock(); if(m_instance_==NULL) { m_instance_=new T(); } g_mutex.unlock(); } return m_instance_; } private: Singleton(){} static T* m_instance_; }; template<typename T> T* Singleton<T>::m_instance_=NULL; } #endif
#include"./Singleton.h" #include<iostream> #include<thread> using namespace std; class Me { public: void Say() { std::cout<<"Hello Word"<<std::endl; } }; void hello() { while(true) { cout<<"he"<<endl; } } int main() { thread first(&test::Singleton<Me>::get); thread second(&test::Singleton<Me>::get); thread third(&test::Singleton<Me>::get); first.join(); second.join(); third.join(); return 0; }
2017年2月27日更新以下內容: 無鎖結構的實現方式,但是經試驗驗證,以現在程式碼的實現方式,耗時和有鎖結構相比無明顯區別: 這可能是因為獲得鎖之後的程式碼只需要瞬間的執行時間,從而沒有明顯因為等待鎖而導致程式碼耗時增加! 程式碼中的__sync_val_compare_and_swap(&m_flag_,0,1)
#ifndef SINGLETON_H
#define SINGLETON_H
//template <typename T>
#include<stddef.h>
#include<iostream>
#include<mutex>
using namespace std;
namespace test
{
//std::mutex g_mutex;
template <typename T>
class Singleton
{
public:
static T* get()
{
if(0==__sync_val_compare_and_swap(&m_flag_,0,1))
{
//g_mutex.lock();
if(m_instance_==NULL)
{
//std::cout<<"get"<<std::endl;
m_instance_=new T();
std::cout<<"ptra:"<<m_instance_<<std::endl;
}
//g_mutex.unlock();
}
std::cout<<"already-1:"<<m_instance_<<std::endl;
return m_instance_;
}
private:
Singleton(){}
static int m_flag_;
static T* m_instance_;
};
template<typename T>
T* Singleton<T>::m_instance_=NULL;
template<typename T>
int Singleton<T>::m_flag_=0;
}
#endif
#include"./Singleton.h"
#include<iostream>
#include<thread>
#include<sys/time.h>
using namespace std;
class Me
{
public:
void Say()
{
std::cout<<"Hello Word"<<std::endl;
}
};
void hello()
{
while(true)
{
cout<<"he"<<endl;
}
}
#define N 10000
int main()
{
//Me* p[10]={NULL};
//Me* p=test::Singleton<Me>::get();
//p->Say();
//thread t(hello);
//t.join();
struct timeval start,end;
gettimeofday(&start,NULL);
thread pool[N];
for(int i=0;i<N;i++)
{
pool[i]=thread(&test::Singleton<Me>::get);
}
for(int i=0;i<N;i++)
{
pool[i].join();
}
gettimeofday(&end,NULL);
std::cout<<std::endl;
std::cout<<"total time:"<<double((end.tv_sec-start.tv_sec)*1000000+(end.tv_usec-start.tv_usec))<<std::endl;
return 0;
}