volatile随笔
1 内存的分类
1 操作系统层面 : 操作系统内存 本地内存 native memory
都属于物理内存 (内存条)
2 JVM层面 : 堆 方法区 虚拟机栈 本地方法栈 程序计数器
都属于物理内存上的一个内存池
3JMM层面 : 主内存 本地内存
本地内存 = 虚拟机栈
主内存 = 堆 + 方法区
2 volatile 作用
1 保证可见性
2 禁止指令重排(保证有序性)
3 不保证原子性
JMM内存模型
八种操作
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锁,锁住地址总线 (硬件)
内联汇编(表示屏障的语句)
- 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关键字之后,会有一个写回的操作,在写回的过程中锁住主内存,使得错误数据不会被读取,写回完成之后解锁
4 new 的执行流程
1 在堆中创建一个空对象,将对象的引用压入虚拟机栈
2 复制栈顶数值并将复制的值压入栈(栈内用两个空对象的引用)
3 执行类默认的构造方法,初始化普通属性
4 把堆中已经完成初始化的对象的指针(栈顶元素)赋值给引用,还有一个赋值给this
推荐阅读
-
volatile随笔
-
volatile底层实现原理
-
volatile关键字实例分析 博客分类: java并发编程 volatile并发线程javasynchronized
-
工作随笔 博客分类: 心情随笔
-
随笔-架构篇-软件架构
-
couchdb漫游指南 博客分类: 随笔 CouchDBPythonMySQLErlang数据挖掘
-
Tokyo Cabinet乱贴(未整理,仅供自己做笔记) 博客分类: 随笔 PythonCC++C#TokyoCabinet
-
被Tokyo Cabinet雷到了 博客分类: 随笔 TokyoCabinet.net
-
多线程编程-volatile关键字(三)
-
java中的volatile关键字