Java中的关键字volatile详解

所属分类: 软件编程 / java 阅读数: 26
收藏 0 赞 0 分享

volatile关键字经常用来修饰变量。不过,volatile本身很容易被误用。本篇就介绍一下volatile的原理和使用方式。

在介绍volatile关键字原理前,我们首先要了解JVM运行时的内存分配逻辑。

对于成员变量i,它存储在堆内存中。每个线程在运行时都会有一个自己的线程栈,线程如果要访问类的成员变量i,会通过引用获取到堆中变量i实际的值10,然后把这个变量值拷贝到自己的栈内存中,作为一个变量副本,之后线程便不再会与堆中的变量有实际联系。每个线程都有一个自己的本地副本,相互隔离。线程访问自己栈内存的效率比访问堆的效率高。线程对变量i值的修改,只会修改自己线程副本中的值,修改结束后,在线程退出前,会把自己线程副本中的值,刷新到堆中。

保证内存可见性

对于如下代码:

public class VolatileTest implements Runnable{
  //volatile
  private static boolean flag = false;
  

  @Override
  public void run() {
    while (!flag){
      System.out.println(Thread.currentThread().getName() +"执行中");
    }
    System.out.println(Thread.currentThread().getName() +"执行完毕");
  }
  
  //main线程
  public static void main(String[] args) throws InterruptedException {
    new Thread(new VolatileTest(), "支线程Volatile").start();
    Thread.sleep(1000);
    flag = true;
  }

}

大多数时候可以正常中断,但是一旦发送异常,便会导致线程死循环。所以需要在flag标志上加一个volatile关键字。对于加了volatile关键字的变量值,线程1修改了这个值的话,会强制将修改值直接写入堆内存中,其他线程各自线程栈中的变量副本无效,只能去堆中取最新的变量值。多个线程之间的内存可见得以保证。
值得注意的是,volatile关键字不能保证原子性。

private volatile int i;

i++;

i ++ 这个操作涉及到获取值,自增和赋值3部分。无法直接完成。上面想要以volatile来实现原子性的写法是错误的。

禁止指令重排

现代JVM对代码的执行顺序有一定的优化。例如:

int a = 4;
int b = 5;
int c = a + b; 

上面3条指令进过JVM优化以后,时间的执行顺序不一定是从上到下,有可能是 第二条--->第一条-->第三条。总之不会影响最终执行结果。

但是在多线程情况下,如下代码就会有风险:

//线程1:
context = loadContext();  
inited = true;       
 
//线程2:
while(!inited ){
 
}
doSomething(context);

线程1的两条语句之间没有依赖性,经过指令重排后,有可能inited置为true以后,context还没有初始化。线程2发现inited为true,以为初始化完成,结束循环,用时间还没有初始化的context去执行doSomething()方法。报错。所以我们可以用volatile关键字修饰inited,保证context初始化。

以上所述是小编给大家介绍的Java中的关键字volatile详解整合,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对脚本之家网站的支持!

更多精彩内容其他人还在看

Java Set简介_动力节点Java学院整理

Set最大的特性就是不允许在其中存放的元素是重复的。接下来通过本文给大家分享java set常用方法和原理分析,需要的的朋友参考下吧
收藏 0 赞 0 分享

Java Timezone类常见问题_动力节点Java学院整理

这篇文章主要介绍了Java Timezone类常见问题的相关资料,需要的朋友可以参考下
收藏 0 赞 0 分享

javaWeb项目部署到阿里云服务器步骤详解

本篇文章主要介绍了javaWeb项目部署到阿里云服务器步骤详解,非常具有实用价值,需要的朋友可以参考下
收藏 0 赞 0 分享

详解使用zxing库生成QR-Code二维码

这篇文章主要介绍了详解使用zxing库生成QR-Code二维码的相关资料,需要的朋友可以参考下
收藏 0 赞 0 分享

java实现对服务器的自动巡检邮件通知

这篇文章主要为大家详细介绍了java实现对服务器的自动巡检邮件通知,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
收藏 0 赞 0 分享

java随机验证码生成实现实例代码

这篇文章主要介绍了java随机验证码生成实现实例代码的相关资料,需要的朋友可以参考下
收藏 0 赞 0 分享

java读取txt文件代码片段

这篇文章主要为大家详细介绍了java读取txt文件的代码片段,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
收藏 0 赞 0 分享

java连接mysql数据库的方法

这篇文章主要为大家详细介绍了java连接mysql数据库的方法,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
收藏 0 赞 0 分享

java 算法之快速排序实现代码

这篇文章主要介绍了java 算法之快速排序实现代码的相关资料,需要的朋友可以参考下
收藏 0 赞 0 分享

详解Spring缓存注解@Cacheable,@CachePut , @CacheEvict使用

这篇文章主要介绍了详解Spring缓存注解@Cacheable,@CachePut , @CacheEvict使用,非常具有实用价值,需要的朋友可以参考下
收藏 0 赞 0 分享
查看更多