前言:
目前咱们对“偏向锁使用场景”大致比较讲究,各位老铁们都需要了解一些“偏向锁使用场景”的相关内容。那么小编同时在网摘上汇集了一些关于“偏向锁使用场景””的相关内容,希望大家能喜欢,小伙伴们快快来学习一下吧!一、使用场景
被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. 抛出异常