场景引入 可见性问题

先来看一张图:

上面的图,是简化版的Java内存模型,一个线程有自己的工作内存,同时还有一个共享的主内存。

线程1和线程2读取数据data时,先从主内存里加载data变量的值到工作内存,然后才可以使用那个值。

假设现在线程1修改了data变量的值为1,然后将这个修改写入到自己的工作内存。那么此时,线程1的工作内存里data的值为1,而主内存里data的值还是0。线程2的工作内存data值也是0。

这就尴尬了,线程1和线程2操作的是用一个变量data,但由于线程本地缓存的存在,导致线程1对data变量的修改,线程2不能及时看到。

这就是Java并发编程中的可见性问题当一个线程修改某个共享变量的值,其他线程是否能够立即知道这个修改。

值得注意的是,上面的Java内存模型是极其简化的,真实的情况远比上面复杂。

volatile的作用及实现原理

要解决上述可见性问题,我们可以使用volatile关键字。

在加入volatile关键字后,线程1只要修改data变量的值,就会在修改工作内存data变量值的同时,强制将修改刷新到主内存中。与此同时,线程2需要读取data变量时,先强制将主内存的值刷新到工作内存中,从而保证线程2每次读取都是最新的值。如下图:

volatile工作原理如上所述,其在JVM底层的实现原理,涉及到内存屏障相关概念。简单来说,JVM在在遇到volatile变量时,在其写操作之后插入一个store屏障,在其读操作之前插入一个load屏障。

Java volatile关键字实现原理的更多相关文章

  1. Java volatile 关键字底层实现原理解析

    本文转载自Java volatile 关键字底层实现原理解析 导语 在Java多线程并发编程中,volatile关键词扮演着重要角色,它是轻量级的synchronized,在多处理器开发中保证了共享变 ...

  2. [Java并发编程(五)] Java volatile 的实现原理

    [Java并发编程(五)] Java volatile 的实现原理 简介 在多线程并发编程中 synchronized 和 volatile 都扮演着重要的角色,volatile 是轻量级的 sync ...

  3. [Java并发编程(三)] Java volatile 关键字介绍

    [Java并发编程(三)] Java volatile 关键字介绍 摘要 Java volatile 关键字是用来标记 Java 变量,并表示变量 "存储于主内存中" .更准确的说 ...

  4. 13、Java并发性和多线程-Java Volatile关键字

    以下内容转自http://tutorials.jenkov.com/java-concurrency/volatile.html(使用谷歌翻译): Java volatile关键字用于将Java变量标 ...

  5. Java Volatile关键字(转)

    出处:  Java Volatile关键字 Java的volatile关键字用于标记一个变量“应当存储在主存”.更确切地说,每次读取volatile变量,都应该从主存读取,而不是从CPU缓存读取.每次 ...

  6. 04 volatile关键字实现原理

    volatile关键字实现原理 1.volatile关键字的语义分析 作用:让其他线程能够马上感知到某个线程多某个变量的修改 保证可见性 对共享变量的修改,其他线程能够马上感知到 保证有序性 在重排序 ...

  7. Java volatile关键字详解

    Java volatile关键字详解 volatile是java中的一个关键字,用于修饰变量.被此关键修饰的变量可以禁止对此变量操作的指令进行重排,还有保持内存的可见性. 简言之它的作用就是: 禁止指 ...

  8. 就是要你懂Java中volatile关键字实现原理

    原文地址http://www.cnblogs.com/xrq730/p/7048693.html,转载请注明出处,谢谢 前言 我们知道volatile关键字的作用是保证变量在多线程之间的可见性,它是j ...

  9. 【转】Java学习---Java中volatile关键字实现原理

    [原文]https://www.toutiao.com/i6592879392400081412/ 前言 我们知道volatile关键字的作用是保证变量在多线程之间的可见性,它是java.util.c ...

随机推荐

  1. 【VS开发】VS2015没修改源文件也导致重新编译的解决办法

    在使用VS2010编译C++程序的时候,每次修改工程中的某一个文件,点击"生成-仅用于项目-仅生成**"时,往往都是整个工程都需要重新编译一遍.由于这个工程代码量太大,每次编译完成 ...

  2. python爬虫4猫眼电影的Top100

    1 查看网页结构 (1)确定需要抓取的字段 电影名称 电影主演 电影上映时间 电影评分 (2) 分析页面结构 按住f12------->点击右上角(如下图2)---->鼠标点击需要观察的字 ...

  3. 查看Linux是CentOS还是Ubuntu

    lsb_release -a

  4. Scala 函数入门之过程、lazy值和异常

    Scala 过程  在Scala中,定义函数时,如果函数体直接包裹在了花括号里面,而没有使用=连接,则函数的返回值类型就是Unit.这样的函数就被称之为过程.过程通常用于不需要返回值的函数. 过程还有 ...

  5. 【LEETCODE】59、数组分类,适中级别,题目:39、48、64

    package y2019.Algorithm.array.medium; import java.util.*; /** * @ProjectName: cutter-point * @Packag ...

  6. 5. JDBC/ODBC服务器

    Spark SQL也提供JDBC连接支持,这对于让商业智能(BI)工具连接到Spark集群上以及在多用户间共享一个集群的场景都非常有用.JDBC服务器作为一个独立的Spark驱动器程序运行,可以在多用 ...

  7. 【1】BIO与NIO、AIO的区别

    一.BIO 在JDK1.4出来之前,我们建立网络连接的时候采用BIO模式,需要先在服务端启动一个ServerSocket,然后在客户端启动Socket来对服务端进行通信,默认情况下服务端需要对每个请求 ...

  8. Helm命令帮助参数

    # helm help The Kubernetes package manager To begin working with Helm, run the 'helm init' command: ...

  9. C# vb .net实现扭曲角特效滤镜图像处理

    在.net中,如何简单快捷地实现Photoshop滤镜组中的扭曲角效果呢?答案是调用SharpImage!专业图像特效滤镜和合成类库.下面开始演示关键代码,您也可以在文末下载全部源码: 设置授权 第一 ...

  10. vue 关于子组件向父组件传值$emit触发无效问题

    先贴上代码 子组件代码 //子组件请求接口,用自己封装的axios getupdate(){ this.$post({ url:this.$apis.unitupdate, postType:'jso ...