锁的疑问及细节

锁升级的过程

​ 无锁状态

​ -> 偏向锁

JVM默认开启偏向锁-XX:+UseBiasedLocking

JVM启动后4s开启-XX:BiasedLockingStartupDelay=4000,查看对象内存布局会看到101

JVM启动过程,会有很多线程竞争,所以默认情况启动时不打开偏向锁,延迟打开。

出现线程竞争锁,则偏向锁升级为轻量级锁。

​ -> 轻量级锁

线程在自己的线程栈桢中生成锁记录(Lock Record) ,用CAS操作将对象mark word设置为

指向自己这个线程的LR的指针,设置成功者得到锁。

如果CAS次数超过阀值、自旋线程超过CPU核数的一半则升级为重量级锁

​ -> 重量级锁

计算过对象的hashCode,将无法进入偏向锁模式

当对象进入偏向状态的时候,Mark Word大部分(23个比特)都用于存储持有锁的线程ID,

这部分空间占用了原有存储对象哈希码的位置,那原来对象的哈希码怎么办?

对象的一致性哈希码(Identity Hash Code),这个值需要保证不变的,

它通过在对象头中存储计算结果来保证第一次计算之后,再次调用该方法取到的哈希值

永远不会变化。因此当一个对象计算过一次哈希码后,它就再无法进入偏向锁状态了;

当一个对象处于偏向锁状态又收到需要计算其一致性哈希码请求时,偏向状态会立即撤销,

并且锁会膨胀为重量级锁。

轻量级锁状态下的对象的hashCode暂存在线程栈的中Lock Record中,

重量级锁状态下的对象的hashCode暂存在ObjectMonitor中。