volatile简单理解

通过java内存模型理解

代码例子理解:

作者:KE meng
链接:https://www.zhihu.com/question/31459750/answer/52061391
来源:知乎
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

来看这个代码:

int fun(int& a)
{
    int b = a;
    int c = a;
    return a+b+c;
}

int main()
{
    int a=1;
    //.........做一些和a无关的事
    return fun(a);
}

这个代码是很好优化的,因为编译器知道a的值是1,参考上下文,编译器又能知道b和c的值也是1,

而且根本没有人用到了a,b,c三个变量,也没有任何人在修改a,b,c三个的值,所以编译器可能就直接

把这个函数优化成:

int main() { return 3; }

了.

这么优化有什么问题吗? 单线程没问题,但多线程就有问题了,如果是多线程,
a的值虽然在当前上下文中不会被修改,但可能正在被其他线程修改啊.于是上面的优化
就不对了. 那么,volatile关键字在这里就可以帮助我们了,volatile关键字提醒编译器:
a可能随时被意外修改.
意外的意思是虽然当前这段代码里看起来a不会变,但可能别的地方正在修改a的值哦.
所谓"别的地方",某些情况下指的就是其他线程了.

那么,如果把代码修改如下:

int fun(volatile int& a)
{
    int b = a;
    int c = a;
    return a+b+c;
}

int main()
{
    volatile int a=1;
    //.........做一些和a无关的事
    return fun(a);
}

编译器就不敢优化了:

int fun(volatile int& a)
{
    int b = a; //这里从内存读一下a吧,谁知道a还等不等于1呢
    int c = a; //这里再从内存读一下a吧,谁知道a还等不等于1呢
    return a+b+c;  //这里也从内存读一下a吧,谁知道a还等不等于1呢
}

int main()
{
    volatile int a=1;
    //.........做一些和a无关的事
    return fun(a); //完全不敢优化啊,鬼知道a变成多少了....
}



总结:被volatile修饰的变量,有线程使用到该变量时都会去主内存里面读取以保证“最新”。

加锁对象obj:A线程使用了obj,此时B线程无法使用,A线程操作obj时直接使用自己工作内存中的obj副本,但不保证A线程在使用

的obj副本是最新的。

加锁对象obj并用volatile:A线程使用obj,此时B线程无法使用,并且obj是从主内存中取的,在加锁的情况下可以保证该obj是最新的。

猜你喜欢

转载自blog.csdn.net/sosmmh/article/details/79298440