关于Singleton (单件),线程安全
很就没写技术相关的blog了,Twitter和Buzz都很少用了,甚至很少有时间静下来思考、敲打键盘
今天面试问到static关键字的时候,有个应试者提到了Singleton的实现,就顺便多问了一点儿,回来自己又查了查
Singleton,单件,四人帮(GoF)写design pattern那本书的时候提出来的,一个进程内有且只有一个实例
说起这些Design Pattern,当时一看,我操,酷毙了,你不知道都不好意思跟别人说你是搞编程的
后来,渐渐的发现,没有银弹,只是有些Design Pattern或许有些淫荡,比如这个Singleton
一个最初的C++标准实现是这样的(S-V1):
//s.h
class Singleton {
private:
Singleton();
static Singleton* instance_;
public:
static Singleton* getInstance() {
if (!instance_)
instance_ = new Singleton();
return instance_; } };
//s.cpp
Singleton* Singleton::pInstance_ = 0;
注意其中构造函数是私有的,所有只能通过getInstance构造,构造前又会先检查,所以只有一个
后来有人说,这样不是线程安全的,哦,那就简单点儿,这样吧(S-V2):
//s.h
class Singleton {
private:
Singleton();
public:
static Singleton* getInstance() {
static Singleton* instance_ = new Singleton();
return instance_; } };
结果有人说,这个是依赖于编译器的,GCC能保证static的初始化不会出问题,但是VC就难说了。
于是,有人觉得既然第一个实现稍微改改就行了,只要加一个淫荡的锁(S-V1.1):
//s.h
class Singleton {
private:
Singleton();
static Singleton* instance_;
public:
static Singleton* getInstance() {
lock_mutex();
if (!instance_)
instance_ = new Singleton();
unlock_mutex();
return instance_; } };
//s.cpp
Singleton* Singleton::pInstance_ = 0;
再后来,有人说这样也不行啊,每次get都加锁,效率太低了吧,那就更加淫荡一点,加锁之前我先check,加锁以后,我再check(S-V1.2):
//s.h
class Singleton {
private:
Singleton();
static Singleton* instance_;
public:
static Singleton* getInstance() {
if (!instance_) {
lock_mutex();
if (!instance_)
instance_ = new Singleton();
unlock_mutex();}
return instance_; } };
//s.cpp
Singleton* Singleton::pInstance_ = 0;
到这里,在搜索网络以前,我曾经认为已经OK了,但是多CPU多线程的复杂超乎想象,有人说,后一个实现不是线程安全的,因为对于instance的读和写并不是原子操作会发生写一半读一半的情况!
好吧,对效率没啥要求每个singleton就只会用个几次的用S-V1.1,没有多线程的用S-V2
========== 以下我也不是很懂的分割线 ==========
难道真的没办法优化S-V1.1了吗?
有办法,那个instance读一半写一半的情况对于int这个类型是不会发生的,那么,就多来一步,check一个int类型的标识吧:
//s.h
class Singleton {
private:
Singleton();
static Singleton* instance_;
static int flag_;
public:
static Singleton* getInstance() {
if (!flag_) {
lock_mutex();
if (!instance_)
instance_ = new Singleton();
unlock_mutex();}
flag_ = 1;
return instance_; } };
嘿嘿,这下你该满足了吧,NO!,还是有问题的,具体啥问题,参见这里 和 那里,代码已经贴太多了。
进行到这里,你应该已经体会到,Singleton是很变态的,Design Pattern是很淫荡的。。。
Singleton最淫荡的地方在于:真正需要它的机会太少太少了,更多讨论参见:
[1] Singleton,你坏。。。在哪里?
[2] Singleton,银弹还是狗屎
[3] Singleton,何日才能用到你
路人甲:OMG,这是什么代码格式啊!
好吧,肯定有人不喜欢这个缩进,但是我敢肯定,肯定有人知道我喜欢Python了


