一、简述:
  关键字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. Java源码解读(一) 8种基本类型对应的封装类型

    说起源码其实第一个要看的应该是我们的父类Object,这里就不对它进行描述了大家各自对其进行阅读即可. 一.八种基本类型 接下来介绍我们的八种基本类型(这个大家都知道吧):char.byte.shor ...

  2. 51nod 1231 记分牌

    链接:http://www.51nod.com/onlineJudge/questionCode.html#!problemId=1231 一个得分合法等价于前k小的得分之和大于等于$\frac{k* ...

  3. 修改mysql密码的四种方法

    方法1: 用SET PASSWORD命令 首先登录MySQL. 格式:mysql> set password for 用户名@localhost = password('新密码'); 例子:my ...

  4. ASP.NET CORE中使用Cookie身份认证

    大家在使用ASP.NET的时候一定都用过FormsAuthentication做登录用户的身份认证,FormsAuthentication的核心就是Cookie,ASP.NET会将用户名存储在Cook ...

  5. layui之事件监听(table)

    这几天在学习layui,感觉这框架挺好用的,前后端都适用,许多原本比较复杂的东西用该框架很容易就能实现. 今天看了table里的事件监听这个知识点. 语法:table.on('event(filter ...

  6. UE4 TSubclassOf VS Native Pointer

    最近看到了TSubclassOf ,所以想要弄清楚跟一般指针的区别~ NativePointer    VS     UClass*      VS     TSubclassOf AActor* p ...

  7. IntersectionObserver实现图片懒加载

    API: https://developer.mozilla.org/en-US/docs/Web/API/Intersection_Observer_API 直接上源码: <!DOCTYPE ...

  8. windows 防火墙拦截nginx的问题

    今天在azure vm上安装了nginx并配置了代理设置,但域名访问始终无法中转,一开始怀疑是nginx的服务没起来,但在本地访问localhost看下如下界面,证明服务是没问题的. 本地访问没问题, ...

  9. 如何把域名解析到网站空间IP上?

    建立网站首要就是要有一个域名和网站空间,怎么把这两者联系在一起呢?这就要通过域名解析,把域名指向空间的IP,让我们能够通过域名访问网站空间.通过域名解析把我们容易记住的域名转化成IP地址,由DNS服务 ...

  10. IIS  发布  dedecms  网站教程

    这里只是说明了配置 php 前后 iis 默认网站属性的变化,其实在配置完 php 后系统的环境变 量等也是发生了相应的变化了的, 这里就不一一列举了, 这些只有在你手动完成 php 的配置 之后才能 ...