谈谈你对volatile理解面试题

本文解析了Java内存模型中volatile的作用,如何解决线程间可见性问题,以及它与原子性和同步机制的区别。重点讲解了volatile如何确保数据的即时更新和工作内存刷新,避免并发编程中的可见性问题。
摘要由CSDN通过智能技术生成

一,先分析为什么用volatile,哪些时候用

是 java 内存模型中,每个线程有⾃⼰的⼯作内存,同时还有⼀个共享的主 内存,比如两个线程都要读data 这个共享变量的值,那么他们都会先从主内存读这两个变量的值

放到自己的工作内存,然后才去使用,所以每个线程都可以读到 data = 1 这个值

在线程代码运⾏的过程中,对 data 的值都可以直接从⼯作内存⾥加载了,不需要再从主内存⾥加载了

在线程代码运⾏的过程中,对 data 的值都可以直接从⼯作内存⾥加载了,不需要再从主 内存⾥加载了

假如说线程 1 修改了 data 变量的值为 2,然后将这个修改写⼊⾃⼰的本地⼯作内存。那么此时,线程 1 的⼯作内存⾥的 data 值为 2

然⽽,主内存⾥的 data 值还是为 1 线程 2 的⼯作内存⾥的 data 值还是1 

在线程 1 的代码运⾏过程中,他可以直接读到 data 最新的值是 2,但 是线程 2 的代码运⾏过程中读到的 data 的值还是 1, 这就导致,线程 1 和线程 2 其实都是在操作⼀个变量 data,但是线程 1 修改了 data 变量的值之 后,线程 2 是看不到的,⼀直都是看到⾃⼰本地⼯作内存中的⼀个旧的副本的值! 这就是所谓的 java 并发编程中的可⻅性问题: 多个线程并发读写⼀个共享变量的时候,有可能某个线程修改了变量的值,但是其他线程看不 到!也就是对其他线程不可⻅

二 volatile 的作⽤及背后的原理

⼀旦 data 变量定义的时候前⾯加了 volatile 来修饰的话,那么线程 1 只要修改 data 变量 的值,就会在修改完⾃⼰本地⼯作内存的 data 变量值之后,强制将这个 data 变量最新的值刷回主内存,必须让主内存⾥的 data 变量值⽴⻢变成最新的值!

如果此时别的线程的⼯作内存中有这个 data 变量的本地缓存,也就是⼀个变量副本的 话,那么会强制让其他线程的⼯作内存中的 data 变量缓存直接失效过期,不允许再次读取和使 ⽤了!

如果线程 2 在代码运⾏过程中再次需要读取 data 变量的值,此时尝试从本地⼯作内存中 读取,就会发现这个 data = 1 已经过期了!

此时,他就必须重新从主内存中加载 data 变量最新的值!那么不就可以读取到 data = 1 这个最 新的值了!

volatile 完美解决了 java 并发中可⻅性的问题! 对⼀个变量加了 volatile 关键字修饰之后,只要⼀个线程修改了这个变量的值,⽴⻢强制刷回 主内存。 接着强制过期其他线程的本地⼯作内存中的缓存,最后其他线程读取变量值的时候,强制重新 从主内存来加载最新的值! 这样就保证,任何⼀个线程修改了变量值,其他线程⽴⻢就可以看⻅了!这就是所谓的 volatile 保证了可⻅性的⼯作原理!

有序性涉及到较为复杂的指令重排、内存屏障等概念,本⽂没提及,但是 volatile 是不能保证 原⼦性的!

如果想要保证原子性得依赖 synchronized、ReentrantLock 等加锁机制来解决,但是像数据更新这种比较小的动作,用锁会严重影响性能,可以使用Atomic类来实现

 

 

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值