1.volatile(可见性和指定重排序)
- JMM定义了Java 虚拟机(JVM)在计算机内存(RAM)中的工作方式。JVM是整个计算机虚拟模型,所以JMM是隶属于JVM的。从抽象的角度来看,JMM定义了线程和主内存之间的抽象关系:线程之间的共享变量存储在主内存(Main Memory)中,每个线程都有一个私有的本地内存(Local Memory),本地内存中存储了该线程以读/写共享变量的副本。本地内存是JMM的一个抽象概念,并不真实存在。它涵盖了缓存、写缓冲区、寄存器以及其他的硬件和编译器优化。
- volatile 修饰后的内容 线程在通过总线的时候 通知总线(监听器)我修改了 volatile修饰的这个变量,那么总线会通知其他线程,缓存中的volatile修饰的变量的内容变了,你们缓存中的对象失效了,然后其他线程在通过总线获取最新的对象内容。
- 缓存一致性协议(MESI)
MESI分别代表缓存行数据所处的四种状态,通过对这四种状态的切换,来达到对缓存数据进行管理的目的。
1. volatile是如何处理指令冲排序的?
- 什么是指令冲排序?指令冲排序是指cpu在执行代码的时候不会按照指定顺序执行,而是有可能先执行第三行,在执行第二行,这种情况就是指令冲排序。
- 什么是DCL 单例?DCL是指 double chack lock,指双重判断锁
public class E {
public static volatile E Instance;
private E(){}
public static E getInstance(){
if(Instance == null){
synchronized (E.class){
if (Instance == null){
Instance = new E();
}
}
}
return Instance;
}
}
- 什么是半初始化?我们new 一个类,这个指令计算机会执行5个指令:new(申请内存)、dup、invokespecial(初始化参数)、astore(引用只指向内存)、return。半初始化是指 3 4 指令 可能优先执行了4 没有执行3,就被其他线程那去使用了。
- DCL单例是否需要加Volatile?需要 为了防止类半初始化问题。
- volatile为什么能实现可见性,和指令重排?因为voletile会增加内存屏障,内存屏障是加增加 lock,执行汇编指令 lock addl , lock作用时独占总线,我修改了内容会通知其他线程改内容失效,其他线程自动更新,并且还会使加锁位置前后代码不能穿插执行。
2. CAS
- CAS 三个值 第一个 预期值 A ,当前值 B ,修改值C,当A = B 把 B修改成C ,怎么实现了 汇编语言lock cmpxchg , cpu 线程 锁总线。
- A-B-A问题 现在有三个线程 一个 i = 0, A 修改了 i的值 改成 1,B把1 拿走 改成了 0 C又把 0 改成了 这种情况下 我们是不知道 i的值 究竟i究竟有没有被修改过。 解决办法 1. 加版本号 2.邮戳
- CAS和sychronized性能谁更高? 分场景,看线程个数和该操作具体时间负责度
- 因为CAS自选消耗CPU性能如果线程过多CPU性能消耗严重,而sychronized是在操作系统排队。
- 如何保证原子性?lock comxchg cpu 线程 锁总线。
3.synchronized
- 重量级锁 jvm发起线程、和锁 都交由os(管理),os处理锁争抢等,处理结束反馈给jvm,jvm反馈给程序。
- 轻量级 jvm自己管理,不交由os管理,CAS自旋竞争。
- 偏向锁 是同步标签,因为大多数同步方法不需要抢锁,所以偏向锁只是记录进入的线程的id,A线程查看id是否是自己,如果不是撤销id,
B线程要获取资源,失败后 偏向锁升级成为 轻量锁(自旋锁)。 - 锁升级
- 偏向锁出现第二个竞争资源的线程升级为轻量锁,轻量锁自旋过程消耗cpc资源过多,升级重量锁。
- 当GC访问该资源时,触发锁降级机制。
- 核心
- wait set 这里存放执行了 wait的线程
- contention list 竞争队列,所有请求锁的线程都放在这里。
- Entry list 存放有资格竞争所的候选者,以你各位contention list 尾部位置竞争激烈才尊放在entry list中
- Ondeck 任意时刻,只能有一个线程竞争锁,他来自contention list的尾部
- owner 获取到锁的对象
- !owner 释放锁的独享
4.类创建内存对象
- markwork
- Class pointer
- instance data
- 补全数据
- 1 + 2 全称 Object head , 2 指向类信息 如创建 object 就是 object.class ,3部分存放 变量信息 4部分为 补全位置 如果前三项内存空间相加 不能被8 整除 就用第4部分补全, 1部分内存放最重要信息是 头部的锁