【锁】---JVM锁原理

最常见的Synchronized,它有三种方式加锁:方法锁,对象锁synchronized(this),类锁synchronized(Demo.Class)。
这三种锁在进入同步代码前都是要获取类的实例或对象的锁。这些对象底层原理是怎么?为什么能达到锁的理念?

一、对象头

一个对象在内存存储分为三块区域:对象头(header)实例数据对齐填充。其中,对象头就是上锁的关键,一般取锁,就是给对象上锁,改变对象头的状态,上锁成功,才能进入同步代码块。

普通对象包括Mark word、class word;
数组对象包括Mark word、class word、数组长度;【锁】---JVM锁原理
对象头的mark word:用于存储对象自身的运行时数据,如哈希码(HashCode)、GC分代年龄、锁状态标志线程持有的锁、偏向线程 ID、偏向时间戳等等。

二、偏向锁、轻量级锁、重量级锁过程

以synchronized为例,实际线程竞争资源就是锁升级的过程。

1、锁升级的原理

【锁】---JVM锁原理
第一个线程进入,JVM在栈帧中建立一个lock record锁记录空间;
拷贝对象头信息进入lock record锁记录中;
JVM使用CAS操作将对象mark word指向lock record【让锁的线程持有者获取执行线程】,同时让lock record的owner指针指向mard word【该线程获得锁】;
设置更新成功,此时锁是只有一个执行线程占用,属于偏向锁;设置更新失败,先检验lock record的owner指针是否指向mard word:
(A)不是,如果有另一个线程来尝试获取锁,发现设置更新失败,此时锁升级为轻量级锁;再有其他的线程竞争,锁再次升级为重量级锁;
(B)是如果是同一个执行线程再次进入,检验发现lock record的owner指针指向mard word,当前执行线程继续进入同步代码块【重入锁原理】。

因此,
偏向锁:JVM默认的是偏向锁,可以配置。偏向第一个访问的线程,始终是只有一个线程占用。
轻量级锁:有第二个线程来竞争资源,那么升级为轻量级锁。
重量级锁:有更多的线程竞争资源,此时升级为重量级锁。