关于双重if的妙用问题。大家一起讨论讨论。。
今天在看书的时候看的这个问题。希望大家一起思考一下,代码如下:
volatile T* pInst = 0;
T* GetInstance()
{
if(pInst == NULL)
{
lock();
if(pInst == NULL)
pInst = new T;
unlock();
}
return pInst;
}
书上说,双重if在这里另有妙用,可以让lock的调用开销降低到最小。求解。。。考虑不出来啊。
可以先不用CPU乱序执行会打乱new那一句的执行,抛开逻辑,只看双重if。
[解决办法]
这个肯定涉及到多线程了,单线程根本就不需要 lock 这些。
在多线程的环境下,外面一个 if 使得绝大多数情况下都不会调用 lock/unlock 函数,当然就提高效率了。
lock()/unlock() 之间还需要使用一个 if 是保证了正确性,在执行 lock() 的过程中,可能其他线程修改了 pInst 变量。需要重新判断一次。
[解决办法]
首先说你这个是单例设计模式,并且考虑到使用多线程的安全性(加锁)。
单例模式的作用就是使该类对象在程序运行始末至多只有一个对象。
这里假设同时有两个线程A、B来访问GetInstance(),A和B同时执行第一个判断语句,结果一样,都进入了代码块,然后A、B又要lock(),但是lock()的设定就是只允许一个线程进入。假设A进入了,B在等待。
A进入后首先判断是不是NULL,也是成功进入代码块,也就是说new了一个对象。然后解锁返回对象。
唤醒B,这是B进入发现第二个判断通过不了(因为A已经new了一个对象)。这样的话B就直接解锁返回对象。
假设只有最外层的判断的话,那么B也会创建一个对象。这样的话就有两个对象在内存中了。
[解决办法]
double check lock
volatile T* pInst = 0;
T* GetInstance()
{
if(pInst == NULL)
{
lock();
if(pInst == NULL)
pInst = new T;
unlock();
}
return pInst;
}
volatile T* pInst = 0;
T* GetInstance()
{
// if(pInst == NULL)
{
lock();
if(pInst == NULL)
pInst = new T;
unlock();
}
return pInst;
}
T* GetInstance()
{
static T* pInst = new T;
return pInst;
}