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. Hbuilder将移动app或者web项目打包

    1. 直接将项目 npm run build 打包生成dist文件 2.将dist文件放到Hbuilderx或者Hbuilder里面,这个时候你会发现他是w的,需要将其转换为A 点击该dist项目右键 ...

  2. Docker+etcd+flanneld+kubernets 构建容器编排系统(1)

    Docker: Docker Engine, 一个client-server 结构的应用, 包含Docker daemon,一个 用来和daemon 交互的REST API, 一个命令行应用CLI. ...

  3. Python实现自动更改系统用户密码,生成随机密码

    算是一个实用的例子,定制系统任务,并将随机密码上传至日志服务器,实现定期修改密码: 部分代码: 1 #!/usr/bin/env python 2 #coding:utf-8 3 import ran ...

  4. alpakka-kafka(9)-kafka在分布式运算中的应用

    kafka具备的分布式.高吞吐.高可用特性,以及所提供的各种消息消费模式可以保证在一个多节点集群环境里消息被消费的安全性:即防止每条消息遗漏处理或重复消费.特别是exactly-once消费策略:可以 ...

  5. JVM诊断及工具笔记(2)使用arthas定位哪里执行了System#gc()

    笔者是汽车之家实时计算平台的一名小伙伴.负责flink平台,数据湖及kafka平台的设计与开发.平时擅长做平台设计,定位及解决各种疑难杂症.第二篇文章,讲的点依旧很小,但是这次图多!!! 在这里感谢支 ...

  6. webbrowser 强制 ie11

    假设winform程序的名称是TestWebBrowser.exe. 1.在开始菜单内输入"regedit.exe",进入注册表编辑器 2.找到注册表项:HKEY_LOCAL_MA ...

  7. 类扩展(Class Extension)

    类扩展(Class Extension) 也有人称为匿名分类 - 作用     - 能为某个类增加额外的属性.成员变量.方法声明     - 一般将类扩展写到.m文件中     - 一般将一些私有的属 ...

  8. Struts2中的过滤器

    过滤器:            过滤器可以处理用户的请求和程序响应的内容,可用于权限控制.编码转换的场合.过滤器是servlet规范中的一部分,不是只有Struts2有. 使用过滤器之前你得定义一个过 ...

  9. CABasicAnimation动画

    使用CABasicAnimation动画: CALayer *znzLayer; = [[CALayer alloc]init]; //创建不断该表CALayer的transform属性动画 CABa ...

  10. LeetCode随缘刷题之整数反转

    package leetcode.day_01_29; /** * 给你一个 32 位的有符号整数 x ,返回将 x 中的数字部分反转后的结果. * 如果反转后整数超过 32 位的有符号整数的范围[− ...