mca马士兵2021高级互联网架构师---synchronized膨胀升级

synchronized膨胀升级

对于synchronized这个关键字,可能之前大家有听过,他是一个重量级锁,依靠底层操作系统的Mutex lock(互斥锁)实现,开销很大,建议大家少用点。但大家可能也听说过,但到了jdk1.6之后,该关键字被进行了很多的优化,已经不像以前那样不给力了,建议大家多使用。

那么它是进行了什么样的优化呢?

img

锁升级过程不可逆!


JDK1.6版本之后对synchronized的实现进行了各种优化,如自旋锁、偏向锁和轻量级锁

并默认开启偏向锁

开启偏向锁:-XX:+UseBiasedLocking -XX:BiasedLockingStartupDelay=0

关闭偏向锁:-XX:-UseBiasedLocking

再介绍这些锁之前,需要了解一个概念:Java对象头

synchronized是悲观锁,在操作同步资源之前需要给同步资源先加锁,这把锁就是存在Java对象头里的,这个对象头长什么样呢?下图以32位JVM中存储内容为例

img

下面看一下锁的升级过程

无锁

无锁没有对资源进行锁定,所有的线程都能访问并修改同一个资源,但同时只有一个线程能修改成功。CAS原理及应用即是无锁的实现。

偏向锁

在大多数情况下,锁总是由同一线程多次获得,不存在多线程竞争,所以出现了偏向锁。其目标就是在只有一个线程执行同步代码块时能够提高性能。如图。注意此时T2并没有发生竞争

img

轻量级锁

是指当锁是偏向锁的时候,被另外的线程所访问,偏向锁就会升级为轻量级锁,其他线程会通过自旋的形式尝试获取锁,不会阻塞,从而提高性能,所谓自旋,就是指当有另外一个线程来竞争锁时,这个线程会在原地循环等待,而不是把该线程给阻塞,直到那个获得锁的线程释放锁之后,这个线程就可以马上获得锁。下图是升级到轻量级锁的过程和自旋的示例

img

img

重量级锁

当系统检查到锁是重量级锁之后,会把等待想要获得锁的线程进行阻塞,被阻塞的线程不会消耗cup。但是阻塞或者唤醒一个线程时,都需要操作系统来帮忙,这就需要从用户态转换到内核态,而转换状态是需要消耗很多时间的,有可能比用户执行代码的时间还要长。

img

综上,偏向锁通过对比Mark Word解决加锁问题,避免执行CAS操作。而轻量级锁是通过用CAS操作和自旋来解决加锁问题,避免线程阻塞和唤醒而影响性能。重量级锁是将除了拥有锁的线程以外的线程都阻塞。

作者:Archer灬 链接:https://www.jianshu.com/p/1bb635f0a7e3 来源:简书 著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

你可能感兴趣的:(java)