Singleton

The basic singleton

//  Singleton.h
class Singleton
{
public:
    static Singleton* Instance(){
        if(!pInstance_)
            pInstance_ = new Singleton;
        return pInstance_;
    }
private:
    Singleton();
    Singleton(const Singleton&);
    Singleton& operator=(const Singleton&);
    ~Singleton();
    static Singleton* pInstance_;
};
//  Singleton.cpp
Singleton* Singleton::pInstance_ = 0;

The code above is the standard of Singleton we learned in school. However, such pattern is not safe in multithread programming. To address this problem, it is best to use synchronized:

class Singleton
{
public:
    static synchronized Singleton* Instance(){
        if(!pInstance_)
            pInstance_ = new Singleton;
        return pInstance_;
    }
};

Dead reference problem and its solutions

//  Singleton.h
class Singleton
{
public:
    static Singleton* Instance(){
        if(!pInstance_){
            if(destroyed_)
                OnDeadReference();
            else
                Create();
        }
        return pInstance_;
}
private:
    static void Create(){
        static Singleton theInstance;//Meyer's Singleton
        pInstance_ = &theInstance;
    }
    static void OnDeadReference(){
        throw std::runtime_error("Dead Reference Detected");
    }
    virtual ~Singleton(){
        pInstance_ = 0;
        destroyed_ = true;
    }
    static Singleton* pInstance_;
    static bool destroyed_;
};
//  Singleton.cpp
Singleton* Singleton::pInstance_ = 0;
bool Singleton::destroyed_ = false;

  Although we successfully solved the undefined behavior problems, we still have to face the unsatisfactory problem. In this case, we would utilize the phoenix singleton pattern.

//  Singleton.h
class Singleton
{
public:
    static Singleton* Instance(){
        if(!pInstance_){
            if(destroyed_)
                OnDeadReference();
            else
                Create();
        }
        return pInstance_;
}
private:
    static void KillPhoenixSingleton();
    static void Create(){
        static Singleton theInstance;//Meyer's Singleton
        pInstance_ = &theInstance;
    }
    virtual ~Singleton(){
        pInstance_ = 0;
        destroyed_ = true;
    }
    static Singleton* pInstance_;
    static bool destroyed_;
};

void Singleton::OnDeadReference(){
    Create();
    new(pInstance_) Singleton;
    atexit(KillPhoenixSingleton);
    destroyed = false;
}

void Singleton::KillPhoenixSingleton(){
    pInstance_->~Singleton();
}
//  Singleton.cpp
Singleton* Singleton::pInstance_ = 0;
bool Singleton::destroyed_ = false;

In this case, the new operator does not allocate memory, it is called the placement new operator, which constructs objects at the address passed. Nevertheless, phoenix singleton pattern is not omnipotent, there is a solution that uses longevity to handle dead reference problem, which will not be discussed in this article

Singleton in multithreaded world

  Singleton object is a shared global resource and all global resources are always suspect for race conditions and threading issues. In this case, we would use the double-checked locking pattern to solve this problem.

Singelton& Singleton::Instance(){
    Lock guard(mutex_);
    if(!pInstance_)
        pInstance_ = new Singleton;
    return *pInstance_;
}

  However, this solution is inconvenient and lack of efficiency, because each call to Instance incurs locking and unlocking the synchronization object. The perfect solution is as follows:

Singelton& Singleton::Instance(){
    if(!pInstance_){
        Lock guard(mutex_);
        if(!pInstance_)
            pInstance_ = new Singleton;
    }   
    return *pInstance_; 
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
单例模式(Singleton Pattern)是一种创建型模式,它保证一个类只有一个实例,并提供一个全局访问点。单例模式通常用于控制某些资源的访问权限,或者在整个系统中只需要一个共享资源的情况下使用。 在单例模式中,类的构造函数必须私有化,这样外部就不能直接实例化该类。同时,类中需要定义一个静态方法,用于获取该类唯一的实例。在第一次调用该方法时,会创建一个实例,并将其保存下来。以后每次调用该方法时,都会返回同一个实例。 例如,下面的代码演示了如何在C++中实现单例模式: ```c++ class Singleton { public: static Singleton& getInstance() { static Singleton instance; // 延迟初始化,保证线程安全 return instance; } private: Singleton() {} // 将构造函数私有化,防止外部实例化 Singleton(const Singleton&) = delete; // 禁止拷贝构造函数 Singleton& operator=(const Singleton&) = delete; // 禁止赋值运算符 }; int main() { Singleton& s1 = Singleton::getInstance(); Singleton& s2 = Singleton::getInstance(); std::cout << std::boolalpha << (&s1 == &s2) << std::endl; // 输出:true return 0; } ``` 在这个例子中,我们定义了一个名为Singleton的类,并将其构造函数私有化,防止外部实例化。同时,我们定义了一个静态方法getInstance,用于获取该类唯一的实例。在getInstance方法中,我们使用了静态局部变量的方式来延迟初始化,保证线程安全。最后,在main函数中,我们多次调用getInstance方法,每次调用都会返回同一个实例。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值