Synchronized的锁升级
JVM对象头在JVM内存区域在堆内存,它包括2部分,一个是Mark Word,一个是Class Pointer。我们的synchronized主要依靠Mark Word。
- Mark Word 存储了对象的锁信息,他的内存空间可能是32也可能是64(根据我们的JVM位数决定)。Mark word 还可以存储对象的hashcode、GC标记、锁状态等信息。
锁升级
无锁状态
在无锁竞争的情况下,对象处于无锁状态,Mark Word中包含对象的hashcode等信息。
偏向锁
偏向锁设计用于减少无竞争情况下的同步开销。
**初次加锁:**当第一个线程进入同步块的时候,JVM会将对象中的MarkDowrd设置为偏向锁状态,并记录当前线程ID。
偏向锁重入: 如果第一个线程在进去同步块的时候,不需要任何同步操作,直接进去同步块执行
**撤销偏向锁:**如果其他线程来了,发现Mark Word偏向锁的偏向线程不是我,然后查看当前偏向的线程是否活跃,如果不活跃就升级为轻量级锁。
轻量级锁 Lightweight Locking
**锁记录:**线程会在栈桢创建一个锁记录,并尝试CAS将对象头的Mark Word替换为指向锁记录的指针(持有锁的线程身份)。
**CAS成功获取:**如果CAS成功就是获取锁成功,进入同步块执行
CAS失败: 升级为重量级锁
CAS自旋的时间是不固定的,可能会根据性能来定。
重量级锁Heavyweight Locking
Monitor: JVM将Mark Word中的指针指向一个Monitor对象,这个Monitor是由操作系统管理的。
**线程堵塞:**未获取到的锁的线程会被刮起,等锁匙放,持有锁的线程释放锁了会唤醒刮起的线程。
**上下文切换:**重量锁会使用操作系统的互斥量来同步线程,但是这样会引发上下文切换和系统调用,开销比较大
锁是否会降级?
在JDK8中,锁不会自动降级。