一、简述:
  关键字Volatile是JAVA虚拟机提供的最轻量级的同步机制,但是它并不容易完全被正确、完整的理解,以致于许多程序员在遇到需要处理多线程数据竞争的时候一律使用synchronized来进行同步,了解volatile变量的语义对后面了解多线程操作的其他特性很有意义。

二、应用:
  当一个变量被定义为volatile之后,它将具备两种特性:
  1. 保证此变量对所有线程的可见性:
    这里的可见性是指当一个线程修改了变量的值,新值对于其他线程来说是可以立即得知的,而普通变量不能做到这一点,普通变量的值在线程间传递需要通过主内存来完成。
    volatile变量在各个线程中是一致的,但基于volatile变量的运算在并发下却不一定是安全的,参见如下案例:

public class Volatile {
public static volatile int count = 0; public static void increaseCount() {
try {
Thread.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
};
count++;
} public static void main(String[] args) {
for (int i = 0; i < 1000; i++) {
new Thread(new Runnable() {
@Override
public void run() {
increaseCount();
}
}).start();
}
System.out.println("count值: " + count);
}
}

  预想的返回值应该是1000,但实际的返回结果值却是小于1000的值,原因在于:

  利用javap发编译后得到代码清单,对应的increaseCount()对应的字节码指令如下:

public static void increaseCount();
Code :
Stack=2, Locals=0, Args_size=0
0: getstatic
3: iconst_1
4: iadd
5: putstatic
8: return

  当getstatic指令把count的值取到操作栈顶是,volatile关键字保证了count在此时是正确的,但是在执行iconst_1、iadd这些指令时,其他线程可能已经把count的值加大了,而在操作栈顶的数据就变成了过期的数据,所以putstatic执行后就可能把较小的count值同步回主内存中了。

  所以,由于volatile变量只能保证可见性,在不符合以下两条规则的运算场景中,仍需要通过加锁来保证原子性:
    1)运算结果并不依赖变量的当前值,或者能够确保只有单一的线程修改变量值;
    2)变量不需要与其他的状态变量共同参与不变约束。

  2. 禁止指令重排序优化
    普通的变量仅仅会保证在该方法的执行过程中所有依赖赋值结果的地方都能获取到正确的结果,而不能保证变量赋值操作的顺序与程序代码中的执行顺序一致,如下场景:
      boolean flag = false;

      线程A:
      doSomeThing();
      flag = true;

      线程B:
      while(!flag){
        doSomeThingElse();
      }

      A.doSomeThing();//调用A线程的方法

    如果定义flag变量时如果没有使用volatile修饰,就有可能由于指令重排序的优化,导致位于线程A中最后一句"flag = true"被提前执行,这样在线程B中调用的A的方法就有可能出现错误,使用volatile可以避免此现象的发生。

三、总结
  volatile的同步性能机制要优于synchronized,但由于虚拟机对锁实行的许多消除和优化,实际上我们很难量化的认为volatile会比synchronized快多少,但volatile跟自己相比而言:volatile变量读操作的性能消耗与普通变量几乎没什么差别,但是写操作则可能慢一些,因为他需要在本地代码中插入许多内存屏障来保证处理器不发生乱序执行。

JAVA关键字Volatile的特性的更多相关文章

  1. Java 关键字volatile的解释

    volatile 关键字特征: 1.可见性,是指线程之间的可见性,一个线程修改的状态对另一个线程是可见的.可以禁止线程的工作内存对volatile修饰的变量进行缓存,并将修改的变量立即写入主存. 2. ...

  2. Java关键字-volatile

    关键字volatile可以说是Java虚拟机提供的最轻量级的同步机制. 一旦某个共享变量(类的成员变量.类的静态成员变量)被volatile修饰之后,那么就具备了两层语义: 1.保证了不同线程对这个变 ...

  3. Java内存模型及Java关键字 volatile的作用和使用说明

    先来看看这个关键字是什么意思:volatile  [ˈvɒlətaɪl] adj. 易变的,不稳定的; 从翻译上来看,volatile表示这个关键字是极易发生改变的.volatile是java语言中, ...

  4. 关于 Java 关键字 volatile 的总结

    1 什么是 volatile volatile 是 Java 的一个关键字,它提供了一种轻量级的同步机制.相比于重量级锁 synchronized,volatile 更为轻量级,因为它不会引起线程上下 ...

  5. java 关键字volatile

    一.Java内存模型 想要理解volatile为什么能确保可见性,就要先理解Java中的内存模型是什么样的. Java内存模型规定了所有的变量都存储在主内存中.每条线程中还有自己的工作内存,线程的工作 ...

  6. java关键字volatile用法详解

    volatile关键字想必大家都不陌生,在java 5之前有着挺大的争议,在java 5之后才逐渐被大家接受,同时作为java的关键字之一,其作用自然是不可小觑的,要知道它是java.util.con ...

  7. 深入汇编指令理解Java关键字volatile

    volatile是什么 volatile关键字是Java提供的一种轻量级同步机制.它能够保证可见性和有序性,但是不能保证原子性 可见性 对于volatile的可见性,先看看这段代码的执行 flag默认 ...

  8. java关键字volatile内存语义详细分析

    volatile变量自身具有下列特性. 1.可见性.对一个volatile变量的读,总是能看到(任意线程)对这个volatile变量最后的写 入. · 2.原子性:对任意单个volatile变量的读/ ...

  9. Java 关键字volatile 与 synchronized 作用与区别

     1,volatile 它所修饰的变量不保留拷贝,直接访问主内存中的.    在Java内存模型中,有main memory,每个线程也有自己的memory (例如寄存器).为了性能,一个线程会在自己 ...

随机推荐

  1. dotnet core webapi +vue 搭建前后端完全分离web架构

    架构 服务端采用 dotnet core  webapi 前端采用: Vue + router +elementUI+axios 问题 使用前后端完全分离的架构,首先遇到的问题肯定是跨域访问.前后端可 ...

  2. 新手必须掌握的Linux命令

    一.命令组成 一个完整的命令通常由  命令名称 [命令参数] [命令对象]  组成. 注意:命令名称.命令参数.命令对象之间用空格键隔开. 二.系统工作命令 查看主机名称 echo $HOSTNAME ...

  3. http://acm.hdu.edu.cn/showproblem.php?pid=1039(水~)

    判读条件 1:有元音字母 2:不能三个连续元音或辅音 3.不能连续两个相同的字母,除非ee或oo #include<cstdio> #include<cstring> #inc ...

  4. HDU--2017

    字符串统计 Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Total Subm ...

  5. [翻译]HTML5 - 会话历史和导航

            原文为:https://w3c.github.io/html/browsers.html#session-history-and-navigation 一.浏览上下文的会话历史记录 浏 ...

  6. 分布式文件系统FastDFS动态扩容

    当用户量越来越大,则集群中某个group总会到达其极限,这时就得扩展集群的容量了. FastDFS的扩容分为对group纵向扩容和横向扩容 纵向扩容 指在同一个group组中增加服务器,实现数据冗余, ...

  7. [基础常识]申请免费SSL证书 - 阿里云云盾证书 - Digicert+Symantec 免费型DV SSL

    https://bbs.aliyun.com/read/573933.html?spm=5176.10695662.1996646101.searchclickresult.72be06dct9Qvw ...

  8. WdatePicker时间插件

    next_door_boy CnBlogs Home New Post Contact Admin Rss Posts - 14  Articles - 5  Comments - 0  WdateP ...

  9. JDBC 元数据 (DatabaseMetaData,ResultSetMetaData )

    Java 通过JDBC获得连接以后,得到一个Connection 对象,可以从这个对象获得有关数据库管理系统的各种信息,包括数据库中的各个表,表中的各个列,数据类型,触发器,存储过程等各方面的信息.根 ...

  10. 1.MAVEN项目的创建与问题的解决

    一.创建一个maven-webapp.(环境:mac和15版本的IDEA) 二.next--->填写groupId(公司单位的名字,你组织的名字)和ArtifactID(有关tomcat,以后用 ...