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

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

  

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

保证内存可见性

  对于如下代码:

public class VolatileTest implements Runnable{  //volatileprivate static boolean flag = false;@Overridepublic 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初始化。

转载于:https://www.cnblogs.com/sunshine-ground-poems/p/10309201.html

Java中的关键字--volatile相关推荐

  1. Java中的关键字volatile解析

    volatile是研究Java并发编程绕不过去的一个关键字,先说结论: volatile的作用: 1.保证被修饰变量的可见性 2.保证程序一定程度上的有序性 3.不能保证原子性 下面,我们将从理论以及 ...

  2. java 死锁 内存消耗_详解Java中synchronized关键字的死锁和内存占用问题

    先看一段synchronized 的详解: synchronized 是 java语言的关键字,当它用来修饰一个方法或者一个代码块的时候,能够保证在同一时刻最多只有一个线程执行该段代码. 一.当两个并 ...

  3. [转载] Java中的关键字含义以及介绍

    参考链接: C++和Java中static关键字的比较 Java关键字是有特别意义的标识符.用来表示一种数据类型,或者表示程序的结构等. Java关键字不能用作变量名.方法名.类名.包名和参数. 以下 ...

  4. java中的关键字英汉

    java中的关键字 初入java记录贴 类: enum(枚举).interface(接口).class(类).extends(继承).implements(实现接口) 对象: new(创建).inst ...

  5. Java中synchronized和volatile有什么区别?

    Java中synchronized和volatile有什么区别? 相关内容 synchronized的问题 什么叫做不完整对象,这个怎么理解呢? 总结 ) 相关内容 1.Java语言为了解决并发编程中 ...

  6. 【Java_基础】Java中Native关键字的作用

    本篇博文转载与:Java中Native关键字的作用 转载于:https://www.cnblogs.com/leiblog/p/10529056.html

  7. java中final关键字的使用

    final 中文翻译为 最终的,在java中也是较为常用的关键字之一. 在java 中 final 关键字可以修饰  类.方法.变量 final 修饰在类上,则表示该类不能被继承,如果里面的成员变量没 ...

  8. java中的关键字static

    原文链接: https://zhuanlan.zhihu.com/p/70110497 昨晚面试中被问到,没能回答出来.这篇答疑文章写得非常好,无一字可增删,遂直接复制. 在平时开发当中,我们经常会遇 ...

  9. java transient_【转】Java中的关键字 transient

    阅读目录 先解释下Java中的对象序列化 在讨论transient之前,有必要先搞清楚Java中序列化的含义: Java中对象的序列化指的是将对象转换成以字节序列的形式来表示,这些字节序列包含了对象的 ...

最新文章

  1. 用WWWGrep来检查你的网站元素安全
  2. 生成对抗网络(Generative Adversarial Network,GAN)
  3. 实用 | 宝藏男孩教你如何魔改 Grafana 主题!
  4. 多线程程序在多核和单核上运行的不同
  5. linux里hba状态_Windows和Linux系统查看HBA卡wwn号的方法 | 系统之家官网
  6. sdut 活动选择问题
  7. oracle清理表空间文件,如何自动删除表空间的文件?
  8. 如何安装Windows7多语言支持
  9. 传输层协议TCP和UDP分析
  10. 植物大战僵尸修改游戏存档
  11. 阿里云服务器被攻击10g怎么进黑洞了?
  12. 【2018年总】——感谢遇见,感谢拥有,感谢失去
  13. 自主创新进展制造世界主要轴承制作强国
  14. 2020G1工业锅炉司炉证考试及G1工业锅炉司炉作业模拟考试
  15. Github testerSunshine/12306 Linux系统部署
  16. 关于yolov5进行FPS游戏的目标检测,实现自动瞄准。
  17. 真我realme V11realmeQ3I root解锁BL 刷magisk MTK 安卓11 root教程 救砖
  18. Dll注入过滤任意Windows控制台命令行输入
  19. CDH6.3.2 hive on tez搭建过程
  20. FileZilla无法连接到服务器

热门文章

  1. 缺失数据em算法python_EM算法
  2. if __name__ == __main___一文搞懂 if __name__ == #39;__main__#39;
  3. java 动态报表 sql,报表SQL
  4. php快速排序分割两部分,php四大算法|冒泡排序|快速排序|二分查找
  5. python 获取唯一值_从Python列表中获取唯一值
  6. Python NumPy教程
  7. 学好C++能够从事哪些岗位?
  8. Join a New Company
  9. 【原】jQuery easyUI 快速搭建前端框架
  10. 阿里云 部署并开启nodejs应用