龙空技术网

Java知识进阶-彻底理解偏向锁原理

架构师的修炼之路 404

前言:

目前咱们对“偏向锁使用场景”大致比较讲究,各位老铁们都需要了解一些“偏向锁使用场景”的相关内容。那么小编同时在网摘上汇集了一些关于“偏向锁使用场景””的相关内容,希望大家能喜欢,小伙伴们快快来学习一下吧!

一、使用场景

被synchronized修饰的方法,如果没有多余的线程来竞争,并且总是由同一个线程多次获取锁。避免每次阻塞线程,从用户态切换到内核态,这种资源的浪费情况引入了偏向锁。

二、偏向过程

对象实例化后,第一个线程来访问,这个时候它是可偏向的,偏向了该线程,让线程持有自己。 线程修改对象头中的 Mark Word 使用CAS操作,并将对象头中的指向线程ID改为指向自己的ID。

同一个线程重入的时候,只需要比较对象中线程ID是否指向自己的ID,如果是自己的,直接持有该对象。

三、偏向流程

3.1 初始化对象

lock = 01 可偏向

ThreadId = 0 无持有线程

3.2 线程1竞争锁

检测 lock == 01 和 ThreadId 是否指向自己 ,如果 “是” 跳转到 3.5 “否” 跳转到3.3

3.3 CAS竞争操作

通过CAS竞争,如果 “成功” 把threadId设置为当前线程1的ID,然后跳转到 3.5。 如果“失败”跳转到 3.4

3.4 CAS竞争失败

说明当前对象,有线程获取到锁。线程进入safepoint(见附录一)位置,并挂起线程,这个时候偏向锁升级为重量锁。继续执行下一步。

3.5 执行同步代码

附录一、

safepoint作用:

标识当前JVM在某个位置是安全的,可以提供暂停。

如:GC的时候,所有线程暂停,调用SafepointSynchronize::begin()方法,最终使所有的线程都进入到safepoint位置,既线程挂起的过程。

safepoint位置:

1. 循环的末尾

这里引入,可以避免某个线程执行时间过长,一直进入不到安全点,导致整个GC被卡住。

防止一直循环先去,线程不进入safepoint,导致其他线程在等待它而不能进入safepoint位置。

2. 方法返回之前

3. 调用方法之后

4. 抛出异常

标签: #偏向锁使用场景 #偏向锁使用场景图片