单例(Singleton)可以说是面试中最常被考到的设计模式了,博主现将单例(Singleton)的各种实现方式奉上,最后博主将向大家展示如何使用modern C++ 中的call_once实现单例(Singleton)。 首先是最简单的线程安全的饿汉实现模式。(所谓饿汉:无论你会不会用到这个实例,都给你创建好。博主想之所以叫饿汉可能是因为这种行事风格很像饿汉吧,异常贪婪。)
class Singleton
{
static Singleton* GetInstance()
{
static Singleton Instance;
return &Instance;
}
private:
Singleton();
};
下来是多线程下不安全的懒汉模式(所谓懒汉:就是你要用这个实例的时候,我再给你创建。)而懒汉之所以多线程下不安全,是因为在下面这段代码中,有可能同时多个线程判断Instance为空,然后出现多个线程都去new的情况。
class Singleton
{
static Singleton* GetInstance()
{
if (nullptr == Instance)
{
Instance = new Singleton();
}
return Instance;
}
private:
Singleton();
static Singleton* Instance;
};
要实现线程安全的懒汉模式,我们可以使用双重检查锁。
#include <mutex>
class Singleton
{
static Singleton* GetInstance()
{
if (nullptr == Instance)
{
std::lock_guard<std::mutex> lock(mu);
if (nullptr == Instance)
{
Instance = new Singleton();
}
}
return Instance;
}
private:
Singleton();
static std::mutex mu;
static Singleton* Instance;
};
最后,重磅炸弹,从C++11开始,C++提供call_once函数,我们可以使用这个函数来实现线程安全的单例(Singleton)。 call_once函数的作用是,这个函数仅会被线程调用一次,而无论有多少线程。 call_once函数要和once_flag变量一起配合使用,另外如果call_once函数绑定不同的once_flag变量,即使绑定相同的函数,这个函数依然是会被调用多次的,即一个once_flag变量只能保证一个函数被调用一次。
class Singleton
{
static Singleton* GetInstance()
{
std::call_once(flag, CreatInstance);
return Instance;
}
private:
Singleton();
static void CreatInstance()
{
Instance = new Singleton();
}
static std::once_flag flag;
static std::mutex mu;
static Singleton* Instance;
};
有帮助的话点个赞吧!有问题的话欢迎大家在评论区批评指正!!!
|