C++ Singleton单例实现方式

1.singleton模式的意图是什么?或者说使用singleton模式解决的问题是什么?
答:保证一个类仅有一个实例,并提供一个访问它的全局访问点,该实例被所有程序模块共享!!!
2.解决上述问题的方法:
方法一: 全局变量或是静态变量
此方法存在的问题:这样做虽然能保证方便的访问实例,但是不能保证只声明一个对象——也就是说除了一个全局实例外,仍然能创建此类的局部实例。当然一不小心可能再创建另一个全局的实例。
方法二: 自己实现个简单的单例(C++版本)。
#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
上述代码有三个点需要说明下:
1.多线程:为防止多线程情况下产生多个单例指针,所以需要添加g_mutex来实现加锁和解锁。
2.double-check:就是 if(m_instance_==NULL) 做了两次判断,别的文章说如果不double-check会导致多个线程访问get函数时导致过多线程挂起,这句话我的体会不深,理解不深刻,鹦鹉学舌了!
3. 现在发现,这个单例模式没有释放类T的实例的操作!—— 貌似智能指针auto_ptr能解决这个问题,或是添加Delete()函数,在某个适当的时候集中销毁!
4.还有构造函数声明为private能够防止在singleton外随意的实例化!
答:亦可以防止防止做为基类使用呀!和 5 的作用岂不是重复了?
5.还有将析构函数声明为private,这种设计我目前还不太理解是为什么?
答:应该是防止被做为基类使用!(2017.02.22)
6.在使用多线程测试此段代码时,使用g++做编译的命令格式是:
g++ -std=c++0x  -Wl,--no-as-needed  main.cpp  -pthread -o test.out

main.cpp部分的代码如下:
#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)  函数可以参考这篇blog!
#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;
}





评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值