zoukankan      html  css  js  c++  java
  • C/C++/Java中的volatile关键字

    volatile提醒编译器它后面所定义的变量随时都有可能改变,因此编译后的程序每次需要存储或读取这个变量的时候,都会直接从变量地址中读取数据。

    如果没有volatile关键字,则编译器可能优化读取和存储,可能暂时使用寄存器中的值,如果这个变量由别的程序更新了的话,将出现不一致的现象,这就是著名的缓存一致性问题。

    Java中的volatile关键字理解:

    先看一段代码,假如线程1先执行,线程2后执行:

    //线程1
    boolean stop = false;
    while(!stop){
        doSomething();
    }
     
    //线程2
    stop = true;

    这段代码是很典型的一段代码,很多人在中断线程时可能都会采用这种标记办法。但是事实上,这段代码会完全运行正确么?即一定会将线程中断么?不一定,也许在大多数时候,这个代码能够把线程中断,但是也有可能会导致无法中断线程(虽然这个可能性很小,但是只要一旦发生这种情况就会造成死循环了)。

      下面解释一下这段代码为何有可能导致无法中断线程。在前面已经解释过,每个线程在运行过程中都有自己的工作内存,那么线程1在运行的时候,会将stop变量的值拷贝一份放在自己的工作内存当中。

      那么当线程2更改了stop变量的值之后,但是还没来得及写入主存当中,线程2转去做其他事情了,那么线程1由于不知道线程2对stop变量的更改,因此还会一直循环下去。

      但是用volatile修饰之后就变得不一样了:

      第一:使用volatile关键字会强制将修改的值立即写入主存;

      第二:使用volatile关键字的话,当线程2进行修改时,会导致线程1的工作内存中缓存变量stop的缓存行无效(反映到硬件层的话,就是CPU的L1或者L2缓存中对应的缓存行无效);

      第三:由于线程1的工作内存中缓存变量stop的缓存行无效,所以线程1再次读取变量stop的值时会去主存读取。

      那么在线程2修改stop值时(当然这里包括2个操作,修改线程2工作内存中的值,然后将修改后的值写入内存),会使得线程1的工作内存中缓存变量stop的缓存行无效,然后线程1读取时,发现自己的缓存行无效,它会等待缓存行对应的主存地址被更新之后,然后去对应的主存读取最新的值。

      那么线程1读取到的就是最新的正确的值。

    参考链接:

    1. C/C++中volatile关键字详解

    2. 详解C中volatile关键字

    3. Java并发编程:volatile关键字解析

  • 相关阅读:
    Mysql常用sql&索引失效场景
    Linux命令demo
    js中浮点数的精度问题
    Linux运行程序出现Cannot execute binary file
    我的第一篇博客文(抽象类练习)
    关于MyEclipse中build path和compiler的jre不匹配
    jQuery操作单选框、多选框是否选中问题
    oracle索引操作
    JS组件多选下拉框Bootstrap之select2 使用心得
    MyEclipse10——java项目clean重新编译
  • 原文地址:https://www.cnblogs.com/yongdaimi/p/9566332.html
Copyright © 2011-2022 走看看