图解volatile
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的更多相关文章
- Java程序员面试必备:Volatile全方位解析
前言 volatile是Java程序员必备的基础,也是面试官非常喜欢问的一个话题,本文跟大家一起开启vlatile学习之旅,如果有不正确的地方,也麻烦大家指出哈,一起相互学习~ 1.volatile的 ...
- [图解Java]读写锁ReentrantReadWriteLock
图解ReentrantReadWriteLock 如果之前使用过读写锁, 那么可以直接看本篇文章. 如果之前未使用过, 那么请配合我的另一篇文章一起看:[源码分析]读写锁ReentrantReadWr ...
- [图解Java]Condition
图解Condition 0. demo 我先给出一个demo, 这样大家就可以根据我给的这段代码, 边调试边看源码了. 还是那句话: 注意"My" , 我把ReentrantLoc ...
- [图解Java]ReentrantLock重入锁
图解ReentrantLock 0. demo 我先给出一个demo, 这样大家就可以根据我给的这段代码, 边调试边看源码了. 还是那句话: 注意"My" , 我把Reentran ...
- Java中this、static关键字的内存图解
Java中的关键字有很多,abstract default goto* null switch boolean do if package nchronzed break dou ...
- volatile关键字的详解-并发编程的体现
xl_echo编辑整理,欢迎转载,转载请声明文章来源.欢迎添加echo微信(微信号:t2421499075)交流学习. 百战不败,依不自称常胜,百败不颓,依能奋力前行.--这才是真正的堪称强大!! 参 ...
- 《Java基础知识》Java锁详解(volatile,synchronized等)
volatile: 让变量每次在使用的时候,都从主存中取. volatile具有synchronized关键字的“可见性”,但是没有synchronized关键字的“并发正确性”,也就是说不保证线程执 ...
- 图解Janusgraph系列-分布式id生成策略分析
JanusGraph - 分布式id的生成策略 大家好,我是洋仔,JanusGraph图解系列文章,实时更新~ 本次更新时间:2020-9-1 文章为作者跟踪源码和查看官方文档整理,如有任何问题,请联 ...
- 从JMM透析volatile与synchronized原理,图文并茂
在面试.并发编程.一些开源框架中总是会遇到 volatile 与 synchronized .synchronized 如何保证并发安全?volatile 语义的内存可见性指的是什么?这其中又跟 JM ...
随机推荐
- gin中提供静态文件服务
package main import ( "github.com/gin-gonic/gin" "net/http" ) func main() { // 静 ...
- 图文并茂理解iptables
原文地址:http://www.zsythink.net/archives/1199 以下是转载内容: iptables详解:图文并茂理解iptables | 朱双印博客 这篇文章会尽量以通俗易懂的方 ...
- CSS实现事件穿透与背景图不跟随滚动条
1. 事件穿透属性:pointer-events: none // auto默认值.none:不捕捉target事件(实现穿透) 用途:当需要使用透明遮罩并且允许点击遮罩下方元素时,或需要使用背景容 ...
- 《Spring Boot 实战纪实》之过滤器
导航 什么是过滤器 Spring的过滤器 Filter定义 过滤的对象 典型应用 过滤器的使用 Filter生命周期 过滤器链 自定义敏感词过滤器 新增自定义过滤器 添加 @WebFilter注解 添 ...
- 布客·ApacheCN 编程/大数据/数据科学/人工智能学习资源 2020.1
公告 我们正在招募项目负责人,完成三次贡献可以申请,请联系片刻(529815144).几十个项目等你来申请和参与,不装逼的朋友,我们都不想认识. 薅资本主义羊毛的 CDNDrive 计划正式启动! 我 ...
- AtCoder ABC213 简要题解
这世道连 \(\rm ABC\) 都要写题解来续命了... A - D 略. E 有如下观察: 对于任意的四个方格,出去之后再回来可以调整为先在内部走到固定位置再走出去. 因此只需要考虑在一开始把内部 ...
- openstack horizon 学习(3) DataTable
上一篇中粗略的讲了下openstack中horizon的dashboard和panel的添加,本打算在这章中对有关于pluggable settings中的配置做详细的总结,然放弃了这念头.原因是搞懂 ...
- 在IDE中普通项目打成jar包
第一步: File---->Project Structe 第二步: 选择From modules.. 第三步:选择对应的Module和对应的JAR,然后点击ok 第四步:选择好对应的属性,然后 ...
- RedHat Linux 忘记密码
一.无法进入系统 在虚拟机开机3秒时按e 选择第二个选项带有quite的那个 进入界面后,在quite后,空格+single 进入单用户模式 然后输入passwd +账号(要修改的账号) 输入新的密码 ...
- Eclipse 找不到或者无法加载主类
最近因为频繁练习JDBC更换了几次驱动jar包,然后突然发现出现了找不到或者无法加载主类的错误, 项目上出现了一个感叹号. 解决方法: 项目-右键 properties-java Build Path ...