C++写单例模式v1版:
class Singlon
{
private:
static Singlon * inst;
public:
static Singlon& instance()
{
if(inst != NULL)
{
return *inst;
}
else
{
inst = new Singlon();
return *inst;
}
} // instance
}; // class Singlon
Singlon* Singlon::inst = NULL;
v1是一份很标准的单例模式代码,但不够实用。
回想C++中的线程互斥,考虑LINUX C下互斥锁,于是乎就有了改进的v2版:
class Singlon
{
private:
static Singlon * inst;
pthread_mutex_t inst_lock;
public:
static Singlon& instance()
{
if(inst != NULL)
{
return *inst;
}
else
{
pthread_mutex_lock(&inst_lock);
if(inst == NULL)
{
inst = new Singlon();
} // if
pthread_mutex_unlock(&inst_lock);
return *inst;
} // else
} // instance
}; // class Singlon
Singlon* Singlon::inst = NULL;
Singlon::inst_lock = PTHREAD_MUTEX_INITIALIZER;
v2中首先直接判断inst是否为NULL,若不为NULL则避免调用互斥锁,因为互斥锁不仅使用系统调用,而且将导致多线程竞争等待,产生睡眠。
发现if语句确实还可以有优化的余地,v3版:
class Singlon
{
private:
static Singlon * inst;
pthread_mutex_t inst_lock;
public:
static Singlon& instance()
{
if(likely(inst != NULL))
{
return *inst;
}
else
{
pthread_mutex_lock(&inst_lock);
if(likely(inst != NULL))
{
pthread_mutex_unlock(&inst_lock);
return *inst;
} // if
else
{
inst = new Singlon();
pthread_mutex_unlock(&inst_lock);
return *inst;
} // else
} // else
} // instance
}; // class Singlon
Singlon* Singlon::inst = NULL;
Singlon::inst_lock = PTHREAD_MUTEX_INITIALIZER;
v3由于互拆锁会导致效用问题,越尽早释放越好,所以将一条if语句拆成两条、迟早释放,并且将条件概率大的情况放到if而非else中,用likely在汇编层上优化。换了个思路,写下v4版:
class Singlon
{
private:
static Singlon * inst;
public:
static Singlon& instance()
{
return *inst;
} // instance
}; // class Singlon
Singlon* Singlon::inst = new Singlon();
v4预先创建好一个对象。虽然浪费空间,但不用再考虑线程互斥问题。
MutexLock使用SpinLock实现互斥,循环检测并休眠。当时突然想起可以直接用SpinLock实现v3的互斥,因为竞争仅发生一次,SpinLock直接采用循环检测不休眠的方式,使用“内存屏障”、“CPU屏障”等技术保证内存和CPU指令的“有序”。v5版如下:
class Singlon
{
private:
static Singlon * inst;
static raw_spinlock_t inst_lock;
public:
static Singlon& instance()
{
if(likely(inst != NULL))
{
return *inst;
}
else
{
spin_lock(&inst_lock);
if(likely(inst != NULL))
{
spin_unlock(&inst_lock);
return *inst;
} // if
else
{
inst = new Singlon();
spin_unlock(&inst_lock);
return *inst;
} // else
} // else
} // instance
}; // class Singlon
Singlon* Singlon::inst = NULL;
spin_lock_init(Singlon::inst_lock);
其实,v5版本还可以优化,例如采用无锁的办法。但总得说来,只是将spin_lock的代码简化了一下内嵌进来。不知道是否有哪位高人可以指点一二,给一个最终优化的C++版单例模式?
《无锁队列的实现》,http://www.kuqin.com/algorithm/20120907/330193.html
转自:http://www.cnblogs.com/icanth/archive/2012/12/10/2811855.html