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. [windows server 2008 站点系列五]一招加速域用戶的文件查找速度
  2. POJ-2481 Cows---树状数组的运用
  3. ITK:切割网格CutMesh
  4. MySQL之三范式:原子性 唯一性 避免数据冗余
  5. 基于 Python 自建分布式高并发 RPC 服务
  6. 动态规划——物品无限的背包问题
  7. 受半导体短缺及疫情影响,丰田已下调9月10月及当前财年产量预期
  8. json格式的简单转换
  9. 在.NET 3.5 平台上使用LINQ to SQL创建三层/多层Web应用系统(源代码下载和PDF文档下载)...
  10. Linux用户-政府篇
  11. 智能车四轮组打工日记(二)——单电机驱动硬件设计
  12. java算法2——费氏数列
  13. Mybatis之分页插件PageHelper工作原理
  14. MySQL查看锁及事务隔离级别的命令
  15. 柬埔寨吴哥旅游:并不仅仅是神秘
  16. x264 i_thead
  17. 一个屌丝程序员的青春(一三八)
  18. Web全栈~26.IO
  19. 安装mavros时,运行 wstool update -t src -j8 时出错解决
  20. opencv python gpu加速_OpenCV中配置CUDA,实现GPU加速

热门文章

  1. vue2.0中组建里面套用组件_vue19 组建 Vue.extend component、组件模版、动态组件 的实例代码...
  2. php imagefill,PHP图像处理技术实例总结【绘图、水印、验证码、图像压缩】
  3. 电脑测试软件_科普丨电脑小白必看的显卡测试小技巧
  4. asm扩容流程_AIX之ASM存储扩容
  5. web集成axis2_AXIS2 Web服务教程
  6. maven安装junit_JUnit安装Maven – JUnit 4和JUnit 5
  7. Django ModelForms
  8. 析构函数c+_了解C ++中的析构函数
  9. C# 窗体全透明,控件不透明
  10. Android Studio 修改项目包名(Xposed)