java:volatile关键字原理
volatile说明
在变量中声明后,能够在所有线程中共享改变量。并且volatile关键字能防止指令重排,即程序读取到volatile时,则不会将程序执行顺序修改。
先了解下内存模型
cpu内存模型

多核cpu在处理数据时,会通过系统总线把主内存中的数据读取副本到高速缓存中的缓存行,当其中一个cpu修改了当前缓存行的数据,会有两种方式保证数据的一致性
1、总线锁:因为高速缓存交互主存是需要通过系统总线的,所以修改后会将总线锁定,阻塞其它CPU访问主存,等当前CPU缓存写入到主存后释放锁。其它CPU才能从主存中读取数据。这种方式效率极低,影响其它CPU访问内存。
2、缓存一致性(MESI):当前CPU缓存行数据修改,通过总线将修改状态广播给其它CPU,让各个CPU根据状态判断本地情况进行响应,是失效还是重新读

java内存模型
JVM内存结构,把内存分为 堆、栈、方法区、本地方法栈和程序计数器。其中堆和方法区被所有线程共享,在内存模型中被成为主内存,而栈、程序计数器属于线程私有,在内存模型中被成为工作内存。
Java内存模型规定所有的变量都是存在主存当中(类似于前面说的物理内存),每个线程都有自己的工作内存(类似于前面的高速缓存)。线程对变量的所有操作都必须在工作内存中进行,而不能直接对主存进行操作。并且每个线程不能访问其他线程的工作内存。
volatile作用
java中内存模型没有像CPU一样的总线来保证线程数据共享。这时候就需要volatile,volatile会强制将每个线程工作内存的变量修改主动的保存主存中。要读取时再从主存中读取

使用volatile达到的线程间变量共享的问题。但是无法保证数据原子性
因为多个线程同时执行,读取赋值写入,那么volatile修饰的变量则会已程序执行时的最后一个线程修改的参数为准。
保障volatile原子性
保障原子性的方式有三种synchronized、lock、atomic
两者是锁住当前变量的操作线程。
atomic是java提供的CAS来实现原子性操作
应用场景
需要通过某个状态控制调用volatile变量的线程(只有一个线程写,其它线程读)
与static区别
相同点:
1、都是为了保证线程共享
2、非原子性(操作变量)
不同点:
volatile唯一的好处就是多线程可以及时获取到最新的主存数据,这点跟static有点区别。static在多线程状态下可能获取不到最新数据。
JVM规范定义了线程对内存间交互操作:
Lock(锁定):作用于主内存中的变量,把一个变量标识为一条线程独占的状态。
Read(读取):作用于主内存中的变量,把一个变量的值从主内存传输到线程的工作内存中。
Load(加载):作用于工作内存中的变量,把read操作从主内存中得到的变量的值放入工作内存的变量副本中。
Use(使用):作用于工作内存中的变量,把工作内存中一个变量的值传递给执行引擎。
Assign(赋值):作用于工作内存中的变量,把一个从执行引擎接收到的值赋值给工作内存中的变量。
Store(存储):作用于工作内存中的变量,把工作内存中的一个变量的值传送到主内存中。
Write(写入):作用于主内存中的变量,把store操作从工作内存中得到的变量的值放入主内存的变量中。
Unlock(解锁):作用于主内存中的变量,把一个处于锁定状态的变量释放出来,之后可被其它线程锁定。
上面一段,只要知道,工作内存中保留了一份主存中的变量副本,因此写操作未必能马上更新到主存,读操作也未必能马上读取到主存中更新后的值,这与cpu时间片有关,能不能读取最新的值看缘分。
参考:
static和volatile的原理及区别:https://blog.csdn.net/x18094/article/details/108429511
Java并发编程:volatile关键字解析:https://www.cnblogs.com/dolphin0520/p/3920373.html
存储器 - 缓存一致性 MESI 协议:如何让多核CPU的高速缓存保持一致:https://www.cnblogs.com/binarylei/p/12590759.html
java:volatile关键字原理的更多相关文章
- Java volatile 关键字底层实现原理解析
本文转载自Java volatile 关键字底层实现原理解析 导语 在Java多线程并发编程中,volatile关键词扮演着重要角色,它是轻量级的synchronized,在多处理器开发中保证了共享变 ...
- [Java并发编程(三)] Java volatile 关键字介绍
[Java并发编程(三)] Java volatile 关键字介绍 摘要 Java volatile 关键字是用来标记 Java 变量,并表示变量 "存储于主内存中" .更准确的说 ...
- 13、Java并发性和多线程-Java Volatile关键字
以下内容转自http://tutorials.jenkov.com/java-concurrency/volatile.html(使用谷歌翻译): Java volatile关键字用于将Java变量标 ...
- Java Volatile关键字(转)
出处: Java Volatile关键字 Java的volatile关键字用于标记一个变量“应当存储在主存”.更确切地说,每次读取volatile变量,都应该从主存读取,而不是从CPU缓存读取.每次 ...
- Java volatile关键字详解
Java volatile关键字详解 volatile是java中的一个关键字,用于修饰变量.被此关键修饰的变量可以禁止对此变量操作的指令进行重排,还有保持内存的可见性. 简言之它的作用就是: 禁止指 ...
- Java volatile关键字实现原理
场景引入 可见性问题 先来看一张图: 上面的图,是简化版的Java内存模型,一个线程有自己的工作内存,同时还有一个共享的主内存. 线程1和线程2读取数据data时,先从主内存里加载data变量的值到工 ...
- 从根源上解析 Java volatile 关键字的实现
1.解析概览 内存模型的相关概念 并发编程中的三个概念 Java内存模型 深入剖析Volatile关键字 使用volatile关键字的场景 2.内存模型的相关概念 缓存一致性问题.通常称这种被多个线程 ...
- java volatile 关键字(转)
volatile这个关键字可能很多朋友都听说过,或许也都用过.在Java 5之前,它是一个备受争议的关键字,因为在程序中使用它往往会导致出人意料的结果.在Java 5之后,volatile关键字才得以 ...
- Java Volatile关键字
在当前的Java内存模型下,线程可以把变量保存在本地内存(比如机器的寄存器)中,而不是直接在主存中进行读写. 这就可能造成一个线程在主存中修改了一个变量的值,而另外一个线程还继续使用它在寄存器中的变量 ...
随机推荐
- 论文笔记:(ICCV2019)KPConv: Flexible and Deformable Convolution for Point Clouds
目录 摘要 一.引言 二.相关工作 投影网络 图卷积网络 逐点多层感知器网络 点卷积网络 三.核点卷积 3.1由点定义的核函数 3.2刚性的或可变形的核 3.3核点网络层 3.4核点网络架构 四.实验 ...
- 单片机学习(一)项目的建立和vscode代码编辑环境的设置
目录 Keil项目的建立 使用vscode进行开发 工欲善其事必先利其器,因此我们先搭建一个比较舒服的开发环境. Keil项目的建立 打开Keil软件点击Project/New uVision Pro ...
- 一文彻底搞清 Gradle 依赖【转】
来源:曾是放牛娃 www.jianshu.com/p/59fd653a54d2 转自:https://mp.weixin.qq.com/s?__biz=MzA3MDMyMjkzNg==&mid ...
- 花1个月时间准备 面试华为,薪资和定级都谈好了却被拒,HR竟说......
说在前面,千万不要频繁跳槽. 本来华为很想去的,面试前花了一个月的时间准备,面试过程挺顺利的,也拒绝了其他的所有面试邀请,而我拒绝其他面试邀请的底气,则是之前面试过程中的良好表现,薪资和定级都谈好了. ...
- 害...原来阿里面试Redis最常问的是它呀
一提到Redis缓存,我们不得不了解的三个问题就是:缓存雪崩.缓存击穿和缓存穿透.这三个问题一旦发生,会导致大量的请求直接请求到数据库层.如果并发压力大,就会导致数据库崩溃.那p0级的故障是没跑了. ...
- Java文件和Java包结构
Java中的包概念 Java中的包是封装一组类,子包和接口的机制.软件包用于: 防止命名冲突.例如,可以有两个名称分别为Employee的类,college.staff.cse.Employee和co ...
- linux联网、远程
使用VMware虚拟机创建linux系统CentOS 7,连接网络以及远程Moba工具. 一.首先安装好VMware虚拟机和CentOS系统,网上很多教程,不在赘述. 二.打开VMware进行配置 1 ...
- Bootstrap 使用小记
1,使用Bootstrap做页面布局,使用card容器 <div class="card"> <div class="card-header" ...
- noip模拟45[真是啥也不会]
noip模拟45 solutions 真是一个题都不会了,然而考完试之后我在10min之内切掉了最后一个题 话说这是为什么呢, 因为最后一个是回滚莫队的大板子,然而我忘记了,不不不,是没有记起来过 T ...
- SQL 练习22
查询出只选修两门课程的学生学号和姓名 --方式1: SELECT Student.SId,Sname from Student WHERE SId in ( SELECT sid from sc GR ...