【深入理解并发编程系列4】JVM内置锁 synchronized关键字详解

ReentrantLock

历史:李二狗看到Synchronized效率太低,自己实现了一套基于AQS的锁。支持可重入,公平,非公平等特性。

Synchronized

历史:1.6之前效率低下,重量锁。
1.6之后进行了升级,追加了锁的升级过程。

偏向锁->轻量级锁->重量级锁。

效率和ReentrantLock差不多

一个图:

锁升级过程

图片

JVM锁膨胀过程

图片

图片

膨胀过程:

  1. 新建实例: 匿名偏向锁。
  2. 第一个线程过来加锁,变成偏向锁。(高23位记录了对象的线程ID)
  3. 第二个线程来后,触发 偏向锁升级,轻量级锁。

重量锁膨胀:

  1. 新建实例,匿名偏向锁
  2. 第一个线程过来,变成偏向锁。
  3. 第二个线程过来,触发轻量级锁。(高30位,指向线程,栈中锁记录的指针-比偏向锁要精确)
  4. 轻量级锁一直被占用,第二个线程自旋无法获取。此时升级成重量级锁。 (高30位存互斥量指针)。

加锁hashcode,会变成轻量级锁的原因:

偏向锁没有hashcode,轻量级锁有个叫replace lock record。在栈帧里。

轻量级锁升级的时候 高30位记录了线程栈上锁的块,lockrecord .hashcode存在这个lockrecord。并且初始的mark word也存在了线程栈上。

hashcode存的位置

图片

什么是Monitor?

一种同步工具,是java的一个对象。所有的java对象天生就是monitor。所有对象在新建的时候都会有一把看不见的锁。叫做内部锁,或者Monitor锁。就是Synchronized锁。MarkWord锁标记为10.其中指针指向 的地址就是Monitor对象的起始地址。在java虚拟机中(hotspot)Monitor是由ObjectMonitor实现的。源码在C++的ObjectMonitor.http文件中。

图片