Intel的CPU分为四个指令集
ring0-1-2-3,自己的应用程序跑在ring3级,Linux内核跑在ring0级,ring0级可以直接访问硬件
ring3级用户态到ring0级内核态需要经过80中断调用
cas compare and swap/compare and set/compare and exchange 最终实现:lock cmpxchg指令(Atomic类下的cmpxchg方法,Atomic原子性)
CAS是轻量级锁
ABA问题 解决方法加版本号
markword工具:JOL Java object layout
synchronized
字节码层级:monitorenter 和monitorexitJVM(hotspot)层级:图
LR lock record
偏向锁是没有必要设置锁竞争机制的
轻量级锁 也是自旋锁 如果有偏向锁先撤销偏向锁 没有直接竞争LR
重量级锁 需要向操作系统申请
synchronized是可重入锁
偏向锁和轻量级锁的重入数记录在线程栈中 LR+1
为什么说synchronized为重量级锁
重量级锁需要惊动操作系统内核,轻量级锁都是在用户态完成的 不需要惊动操作系统内核
因为synchronized是跑在JVM上的,JVM对于OS的kernel来说就是一个普通的应用程序,想加锁的话就需要向kernel申请,也就是说synchronized需要经历从用户态到内核态的访问,之后内核态再返回给用户态的过程,synchronized会首先申请在轻量级这部分(用户态)完成,完成不了才会访问内核态
new一个对象时 内存布局什么样
| markword | 8K |
|---|---|
| classpointer | 4K |
| instancedata | 根据类型决定大小 |
| padding | 64位虚拟机 前面合计不能够被8整除,补齐 |
堆内存中的布局:生成一个8k的markword 4K的classpointer,classpointer指向class例如Object.class 成员变量类型的字节(例如int 4字节)前三项合计不是8的整数倍时 再补到8的倍数
markword记录了哪些信息
锁 GC hashcode
自旋锁什么时候上升为重量级锁
竞争加剧的时候:有线程超过10次自旋,-XX:PreBlockSpin,或者自旋线程超过CPU核数的一半,JDK1.6之后加入自适应自旋AdaPatIve Self Spinning,JVM可以自己控制
为什么有自旋锁还需要重量级锁
自旋是消耗CPU资源的,如果锁的时间长,或者自旋线程多,CPU会被大量消耗,重量级锁有等待队列(waitset),所有拿不到锁的进入等待队列,不需要消耗CPU资源
偏向锁是否一定比自旋锁效率高
不一定,在明确知道会有多线程竞争的情况下,偏向锁肯定会涉及锁撤销,这时候直接使用自旋锁
JVM启动过程,会有很多线程竞争,所以默认情况启动时不打开偏向锁,过一段时间后再打开