咱们都很清楚一个简单的单例模式该怎样去实现:构造函数声明为private或protect防止被外部函数实例化,内部保存一个private static的类指针保存惟一的实例,实例的动做由一个public的类方法代劳,该方法也返回单例类惟一的实例。面试
上代码: 安全
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
|
class
singleton
{
protected
:
singleton(){}
private
:
static
singleton* p;
public
:
static
singleton* instance();
};
singleton* singleton::p = NULL;
singleton* singleton::instance()
{
if
(p == NULL)
p =
new
singleton();
return
p;
}
|
这是一个很棒的实现,简单易懂。但这是一个完美的实现吗?不!该方法是线程不安全的,考虑两个线程同时首次调用instance方法且同时检测到p是NULL值,则两个线程会同时构造一个实例给p,这是严重的错误!同时,这也不是单例的惟一实现!函数
单例大约有两种实现方法:懒汉与饿汉。性能
特色与选择:spa
线程不安全,怎么办呢?最直观的方法:加锁。线程
class singleton { protected: singleton() { pthread_mutex_init(&mutex); } private: static singleton* p; public: static pthread_mutex_t mutex; static singleton* initance(); }; pthread_mutex_t singleton::mutex; singleton* singleton::p = NULL; singleton* singleton::initance() { if (p == NULL) { pthread_mutex_lock(&mutex); if (p == NULL) p = new singleton(); pthread_mutex_unlock(&mutex); } return p; }
此方法也很容易实现,在instance函数里定义一个静态的实例,也能够保证拥有惟一实例,在返回时只须要返回其指针就能够了。推荐这种实现方法,真得很是简单。 指针
class singleton { protected: singleton() { pthread_mutex_init(&mutex); } public: static pthread_mutex_t mutex; static singleton* initance(); int a; }; pthread_mutex_t singleton::mutex; singleton* singleton::initance() { pthread_mutex_lock(&mutex); static singleton obj; pthread_mutex_unlock(&mutex); return &obj; }
为何我不讲“线程安全的饿汉实现”?由于饿汉实现原本就是线程安全的,不用加锁。为啥?本身想!code
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
class
singleton
{
protected
:
singleton()
{}
private
:
static
singleton* p;
public
:
static
singleton* initance();
};
singleton* singleton::p =
new
singleton;
singleton* singleton::initance()
{
return
p;
}
|
是否是特别简单呢?blog
以空间换时间,你说简单不简单?ci
面试的时候,线程安全的单例模式怎么写?确定怎么简单怎么写呀!饿汉模式反而最懒[正经脸]!