欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

volatile随笔

程序员文章站 2024-03-24 18:28:46
...

1 内存的分类

1 操作系统层面 : 操作系统内存 本地内存 native memory
都属于物理内存 (内存条)

2 JVM层面 : 堆 方法区 虚拟机栈 本地方法栈 程序计数器
都属于物理内存上的一个内存池

3JMM层面 : 主内存 本地内存

本地内存 = 虚拟机栈
主内存 = 堆 + 方法区

2 volatile 作用

1 保证可见性
2 禁止指令重排(保证有序性)
3 不保证原子性

JMM内存模型
volatile随笔
八种操作
volatile随笔

3 volatile 如何保证有序性

volatile 禁止指令重排,保证了有序性
1 指令重排分为两个阶段
编译阶段: Java层面(字节码文件)并没有做指令重排
运行阶段: (jdk源码阶段)产生指令重排

2 为什么会产生指令重排
CPU乱序执行

3 volatile如何解决运行期指令重排
3.1
as - if - serial 规范 : 单线程运行下,不允许改变运行结果
happens - bdfore 实现
1 对象的初始化动作要优于finilize() 的调用
2 …

规范 预防的是宏观上的指令重排

3.2 内存屏障
1 编译阶段(编译屏障):保证操作的是内存
2 运行阶段(内存屏障): 发生于CPU内部

CPU提供的屏障
1 fence族 : mfence lfence sfence (串行化读写)
2 lock指令: lock锁,锁住地址总线 (硬件)
volatile随笔

内联汇编(表示屏障的语句)

 - asm - volatile ("lock ; add ( $0 , 0 (% % rsp": : : "c" , "memory");

“c” , “memory” : 编译屏障

  • asm - volatile ("lock : 内存屏障 ,C , C++层面的volatile,禁止编译器优化无效代码

CPU写内存方式
1 同步写 : CPU把数据写入store buffer,然后写入内存
2 异步写 : CPU把数据写入store buffer,等待CPU空闲再把buffer中的数据写入内存(CPU默认采用)

因为CPU默认是异步写的方式,所以需要内存屏障把异步写方式改成近似同步写,使得读写操作只能按序执行,CPU无法乱序执行,最终是为了保证异步刷回内存的时间更短,读写有序

3 volatile 如何保证可见性

volatile随笔

加了volatile关键字之后,会有一个写回的操作,在写回的过程中锁住主内存,使得错误数据不会被读取,写回完成之后解锁

4 new 的执行流程

1 在堆中创建一个空对象,将对象的引用压入虚拟机栈

2 复制栈顶数值并将复制的值压入栈(栈内用两个空对象的引用)

3 执行类默认的构造方法,初始化普通属性

4 把堆中已经完成初始化的对象的指针(栈顶元素)赋值给引用,还有一个赋值给this