volatile关键字对过度优化的使用
volatile的作用: 作为指令关键字,确保本条指令不会因编译器的优化而省略,且要求每次直接读值.(优化器在用到这个变量时必须每次都小心地重新读取这个变量的值,而不是使用保存在寄存器里的备份)
举例:
x=0;
//Thread1 Thread2
lock(); lock();
x++; x++;
unlock(); unlock();
Thread1先进入加锁区域,Thread2被lock()阻塞前,如果先将x=0放入了寄存器中,那么加锁也就没有意义了。
使用volatile关键字可解决上述问题
Singleton模式下CPU乱序问题
先看如下代码
Volatile T* pInst = 0;
T* GetInstance()
{
if(!pInst)
{
lock();
if(!pInst)
pInst = new T;
unlock();
}
return pInst;
}
这样的代码在CPU乱序下的问题如下:
pInst = new T;实际上包含了3个步骤:
(1)分配内存;
(2)调用构造函数;
(3)将内存地址返回并赋值给pInst
然而(2)(3)步骤是可以颠倒的。即CPU在构造函数被调用完成之前就已经返回了地址;当其他线程此时使用该指针则会出现错误。
解决此问题的方法为barrier指令
Volatile T* pInst = 0;
T* GetInstance()
{
if(!pInst)
{
lock();
if(!pInst)
{
T *temp= new T;
barrier();//
pInst = temp;
}
unlock();
}
return pInst;
}