volatile是什么

    出去面试的时候,很多面试官都会问你:说说你对volatile的理解。

    下面我将用图的方式告诉大家,volatile是什么?

    

    如上图所示:每个线程都有自己的工作内存,同时还能访问共享内存。

    当两个线程,他们的代码都i需要读取X的值时候, 那么他都会从主内存里加载X变量到自己的工作内存,然后才可以使用X。

    这样,在线程的代码运行过程中,对X的值就可以直接从工作内存中加载了,不需要再从主内存中加载了。

    那么问题来了,为啥每次一定要让线程从工作内存的来读取变量的副本呢,而不是直接去读取共享内存的变量值X不行吗?

      因为线程运行的代码是对应一些指令,是CPU执行的,但是CPu每次执行指令运算,也就是执行我们写的那一大坨代码的时候,是要每次修改这个变量的值的,都是从主内存加载,性能会变差。

      线程内有自己的工作内存的概念,类似于一个本地的缓存,性能会很大提升。

    我们来设想一下,如果线程一,修改了X的值为1,然后将这个修改写入自己的工作内存,那么此时线程1的工作内存值为1.

    而主内存的X还是0,线程2的X还是0,怎么办呢?

    

    如上图所示,线程1和线程2其实都在操作X,但是线程1修改了X,线程2看不到,一直都是看到自己本地工作内存中一个副本的值!

    这就是Java并发编程的可见性问题:

    多个线程并发读写一个共享变量的时候,有可能某个线程修改了变量的值,但是其他线程看不到,也就是对其他线程不可见。

  volatile的作用及背后的原理

    要解决并发编程中的可见性问题,那要怎么办呢,你只要给这个变量定义的加上一个volatile,那么就可以解决了。

    volatile的作用啥是?

      1、一旦X变量定义了volatile来修饰的话,那么线程1,只要修改了X的值,就会在修改完自己工作内存的X变量之后,强制将这个X的值刷新到主内存,必须让主内存的值变成最新的值,整个过程如下图所示:

      2、其二,如果此时有别的线程的工作内存中有这个X变量的本地缓存,也就是一个变量副本的话,那么会让其他线程的工作内存X变量缓存直接失效过期,不允许再次读取和使用,如下图所示:

      3、如果线程2在代码运行中,再次需要读取X变量的值,那么尝试从本地工作内存读取,会发现这个X=0已经过期了。

      也就是必须重新从主内存中加载变量最新的值,那么不就可以读取到X=1的最新的值,整个过程如下图所示:

    对于一个变量加了volatile关键字修饰之后,只要一个线程修改了这个变量的值,立马会强制刷新回主内存,接着强制过期其他线程的工作内存的缓存,最后其他线程读取变量的时候,强制从主内存加载最新的值。

    这样就保证了,任何一个线程修改了变量的值,其他线程立马就可以看见了。

  总结&提醒

    volatile的主要作用还是保证可见性以及有序性。

    有序性涉及到指令重排,内存屏障等概念,但是volatile还是不能保证原子性的。

    也就是说,volatile主要解决一个线程修改了变量的值后,其他线程可以立马读取到最新的值。

    但是如果多个线程同时修改一个变量的值,那还是会可能出现多线程并发安全问题,导致数据修改错乱,也就是说volatile是不负责解决这个问题,也就是不负责解决原子性问题。

    原子性问题主要依靠synchronized,ReentrantLock等加锁机制来解决。

图解volatile的更多相关文章

  1. Java程序员面试必备:Volatile全方位解析

    前言 volatile是Java程序员必备的基础,也是面试官非常喜欢问的一个话题,本文跟大家一起开启vlatile学习之旅,如果有不正确的地方,也麻烦大家指出哈,一起相互学习~ 1.volatile的 ...

  2. [图解Java]读写锁ReentrantReadWriteLock

    图解ReentrantReadWriteLock 如果之前使用过读写锁, 那么可以直接看本篇文章. 如果之前未使用过, 那么请配合我的另一篇文章一起看:[源码分析]读写锁ReentrantReadWr ...

  3. [图解Java]Condition

    图解Condition 0. demo 我先给出一个demo, 这样大家就可以根据我给的这段代码, 边调试边看源码了. 还是那句话: 注意"My" , 我把ReentrantLoc ...

  4. [图解Java]ReentrantLock重入锁

    图解ReentrantLock 0. demo 我先给出一个demo, 这样大家就可以根据我给的这段代码, 边调试边看源码了. 还是那句话: 注意"My" , 我把Reentran ...

  5. Java中this、static关键字的内存图解

    Java中的关键字有很多,abstract  default  goto*  null  switch  boolean  do  if  package  nchronzed  break  dou ...

  6. volatile关键字的详解-并发编程的体现

    xl_echo编辑整理,欢迎转载,转载请声明文章来源.欢迎添加echo微信(微信号:t2421499075)交流学习. 百战不败,依不自称常胜,百败不颓,依能奋力前行.--这才是真正的堪称强大!! 参 ...

  7. 《Java基础知识》Java锁详解(volatile,synchronized等)

    volatile: 让变量每次在使用的时候,都从主存中取. volatile具有synchronized关键字的“可见性”,但是没有synchronized关键字的“并发正确性”,也就是说不保证线程执 ...

  8. 图解Janusgraph系列-分布式id生成策略分析

    JanusGraph - 分布式id的生成策略 大家好,我是洋仔,JanusGraph图解系列文章,实时更新~ 本次更新时间:2020-9-1 文章为作者跟踪源码和查看官方文档整理,如有任何问题,请联 ...

  9. 从JMM透析volatile与synchronized原理,图文并茂

    在面试.并发编程.一些开源框架中总是会遇到 volatile 与 synchronized .synchronized 如何保证并发安全?volatile 语义的内存可见性指的是什么?这其中又跟 JM ...

随机推荐

  1. for each ……in

    使用一个变量迭代一个对象的所有属性值,对于每一个属性值,有一个指定的语句块被执行. 作为ECMA-357(E4X)标准的一部分,for each...in语句已被废弃,E4X中的大部分特性已被删除,但 ...

  2. gorm中的删除

    删除 删除一条记录 删除一条记录时,删除对象需要指定主键,否则会触发 批量 Delete,例如: db.Debug().Where("id = ?", 6).Delete(new( ...

  3. Github基于Web的编辑器

    在 GitHub 存储库中使用基于 Web 的编辑器来创建和提交代码更改. 关于 GitHub 基于 Web 的编辑器 基于 Web 的编辑器引入了全新的轻量级编辑体验,可完全在您的浏览器中运行.使用 ...

  4. PowerDotNet平台化软件架构设计与实现系列(12):HCRM人员管理平台

    技术服务于业务,良好的技术设计和实现能够大幅提升业务质量和效率. PowerDotNet已经形成了自己的开发风格,很多项目已被应用于生产环境,可行性可用性可靠性都得到了生产环境验证. 编程是非常讲究动 ...

  5. 基于Redis&MySQL接口幂等性设计

    基于Redis&MySQL接口幂等性设计 欲把相思说似谁,浅情人不知. 1.幂等 幂等性即多次调用接口或方法不会改变业务状态,可以保证重复调用的结果和单次调用的结果一致. 2.幂等使用场景 前 ...

  6. macOS Monterey 12.12.2 (21D49) 正式版 ISO、IPSW、PKG 下载

    本站下载的 macOS Monterey 软件包,既可以拖拽到 Applications(应用程序)下直接安装,也可以制作启动 U 盘安装,或者在虚拟机中启动安装. 2022 年 1 月 27 日,m ...

  7. eureka的简单介绍,eureka单节点版的实现?eureka的自我保护?eureka的AP性,和CP性?

    注意!!! 这是对上一篇博客 springcloud的延续,整个项目的搭建,来源与上一篇博客.一.什么是eureka? // eureka是一个注册中心,实现了dubbo中zookeeper的效果! ...

  8. Java-在数组中遍历出最值

    在操作数组时,经常需要获取数组中元素的最值. 代码 public class Example31{ public static void main(String[] args){ int[] arr= ...

  9. 微服务中的CAP原则

    CAP原则:指的是在一个分布式系统中,Consistency(一致性). Availability(可用性).Partition tolerance(分区容错性),三个要素最多同时实现两点不可能同时实 ...

  10. 接口里的default,static方法

    我们都知道接口里的变量默认隐含类型是public static final,也是就是说是常量.而方法默认类型是public abstract,所以接口的方法都是抽象方法,但是事实真的是这样吗? 我的P ...