专栏首页风中追风volatile关键字解析
原创

volatile关键字解析

在给 volatile关键字解析 之前 希望看本文的朋友对Java内存模型有一定的了解;不了解的朋友可以先看看Java内存模型

一、volatile关键字有什么用呢?

1、保证了不同线程访问同一个变量时的可见性,也就是说A线程修改了一个变量的值,B线程C线程能马上就能看到这个变量的最新值。

2、禁止指令的重排序。

1、volatile关键字能保证可见性吗?

看一个简单的例子:

[java] view plain copy

  1. <span style="font-size:18px;">//线程1
  2. int i = 1;  
  3. i = 100;  
  4. //线程2
  5. int k = i ;</span>  

如果了解Java内存模型,相信你一定可以一眼看出,在多线程的情况下,线程1的是CPU1,执行线程2的是CPU2。由上面的分析可知,当线程1执行 i =100这句时,会先把i的初始值加载到CPU1的高速缓存中,然后赋值为100,那么在CPU1的高速缓存当中i的值变为100了,却没有立即写入到主存当中。此时线程2执行 k = i,它会先去主存读取i的值并加载到CPU2的缓存当中,注意此时内存当中i的值还是0,那么就会使得 k 的值为0,而不是100,如果加了volatile 呢?

加上了volatile,就相当于给访问 volatile 修饰变量的线程 一双火眼金睛~

线程1会把volatile修饰的这个变量的每一个操作后的值都告诉主存,其他线程任何时候都可以读取到最新最正确的值;

2、volatile关键字能保证有序性吗?

看一个简单的例子:

[java] view plain copy

  1. <span style="font-size:18px;">//线程1  
  2. resourse =  config.load(); //语句1:假设是加载一个文件完成初始化;  
  3. boolean flag = true;//语句2   
  4. //线程2  
  5. if(flag=false){    
  6.     Thread.sleep(1000);    
  7. }    
  8. add(<span style="font-family:Verdana, Arial, Helvetica, sans-serif;">resourse</span>);</span>  

Java内存模型中我们举过这个例子,在多线程的情况下:如果语句2先执行了,可能导致发生异常;如果给flag变量加上volatile 关键字,volatile关键字能保证在它之前的语句1执行了,才会执行它自己语句2;

再看一个单线程的例子:

[java] view plain copy

  1. <span style="font-size:18px;">a = 1;//语句1
  2. b = 2;//语句2
  3. volatile boolean flag = true;//语句3
  4. a = 4;//语句4
  5. b = 5;//语句5</span>

我们知道由于flag变量为volatile变量,那么在进行指令重排序的过程的时候,不会将语句3放到语句1、语句2前面,也不会讲语句3放到语句4、语句5后面。但是要注意语句1和语句2的顺序、语句4和语句5的顺序是不作任何保证的。

并且volatile关键字能保证,执行到语句3时,语句1和语句2必定是执行完毕了的,且语句1和语句2的执行结果对语句3、语句4、语句5是可见的。

3、volatile关键字能保证原子性吗?

volatile并不能保证一个操作是原子操作,为了让一个操作是原子操作可以使用synchronized关键字和Lock锁来实现;

二、volatile 使用场景

在多线程的情况下,需要进行读(获取)操作时可以使用volatile 关键字来修饰变量,在进行写操作时,还是需要使用synchronized关键字和Lock锁来实现。

举个简单的例子:concurrenthashmap 的 put 操作是要加锁才能保证把节点放进“桶”的时候是线程安全的,

而 get 操作是不需要加锁的,原因就是 节点 的属性 使用了volatile 关键字;

原创声明,本文系作者授权云+社区发表,未经许可,不得转载。

如有侵权,请联系 yunjia_community@tencent.com 删除。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • volatile和synchronized 实现原理的差别

    提到volatile 和 synchronized 的时候不得不提到的一个东西就是JMM(java Memory Model)java内存模型。

    矿泉水
  • Java内存模型分析

    计算机在执行程序时,每条指令都是在CPU中执行的,而执行指令过程中,势必涉及到数据的读取和写入。

    矿泉水
  • try,finally中都有return时程序的执行顺序

     在Java中当try、finally语句中包含return语句时,执行情况到底是怎样的,finally中的代码是否执行,大家各有各的说法,刚好今天有个朋友问了...

    矿泉水
  • volatile关键字解析

    在给 volatile关键字解析 之前 希望看本文的朋友对Java内存模型有一定的了解;不了解的朋友可以先看看Java内存模型

    用户2141593
  • Python | 面试必问,线程与进程的区别,Python中如何创建多线程?

    其实关于元类还有很多种用法,比如说如何在元类当中设置参数啦,以及一些规约的用法等等。只不过这些用法比较小众,使用频率非常低,所以我们不过多阐述了,可以在用到的时...

    TechFlow-承志
  • (三)一个服务器程序的架构介绍

    本文将介绍我曾经做过的一个项目的服务器架构和服务器编程的一些重要细节。 一、程序运行环境 操作系统:centos 7.0 编译器:gcc/g++ 4.8.3 c...

    范蠡
  • Linux例行性工作排程 (crontab)

    crontab是Unix和Linux用于设置周期性被执行的指令,是互联网很常用的技术,很多任务都会设置在crontab循环执行,如果不使用crontab,那么任...

    用户3094376
  • 聊聊flink的Execution Plan Visualization

    本文主要研究一下flink的Execution Plan Visualization

    codecraft
  • 聊聊flink的Execution Plan Visualization

    本文主要研究一下flink的Execution Plan Visualization

    codecraft
  • Windows窗口消息和消息队列

    所有基于事件驱动的操作系统中的GUI程序,都会在主线程中运行一个消息泵来从消息队列中取出消息并执行对应的处理逻辑。消息队列中的消息除了由系统产生外,还提供了对应...

    欧阳大哥2013

扫码关注云+社区

领取腾讯云代金券