synchronized和reentrantLock的底层实现

实现synchronized的基础: Java对象头 + Monitor

对象头的结构如下:

虚拟机位数 头对象结构 说明
32/64bit Mark Word 默认存储对象的hashcode,分代年龄,锁类型,锁标志位等信息。
32/64bit Class Metadata Address 类型指针指向对象的类元数据,JVM通过这个指针确定该对象是哪个类的数据。

Mark Word的说明图:

而对于Monitor,每个Java对象天生自带一把看不见的锁(内部锁/Monitor锁)。

Monitor锁的竞争与释放如下图所示:

在早期的Java版本中,synchronized属于重量级锁,依赖于Mutex Lock实现。线程之间的切换需要从用户态置换到核心态,开销很大。在 Java 6之后,synchronized性能得到了很大提升。引入了四级锁结构,无锁->偏向锁->轻量级锁->重量级锁。

ReentrantLock的实现基于著名的AQS。当多个线程调用同一个ReentrantLock对象的lock()方法时,大致原理是每个线程都尝试去修改锁对象内一个状态属性state(继承自AbstractQueuedSynchronizer)的值,这个修改过程采用了CAS(compare and swap)技术即每个线程都想把这个变量从数据0改变成1. 如果一个线程修改成功则成为锁对象的owner,否则 LockSupport.park中止该线程,并调用该线程的interrupt方法设置线程的interrupted状态,并创建一个node存放该线程并将node加入链表中。当某线程a 调用unlock方法时,从链表中取出a线程对应node的next节点并调用LockSupport.unpark给对应线程一个许可让其继续执行。(以非公平锁为例)

ReentrantLock和synchronized的可重入性实现: https://www.jianshu.com/p/ca7df6c1110f

猜你喜欢

转载自blog.csdn.net/qian_348840260/article/details/106478026