「这是我参与2022首次更文挑战的第18天,活动详情查看:2022首次更文挑战」。
锁的升级和对比
在JDK1.6中引进了偏向锁和轻量级锁。使用锁一共有4种形态,随着锁的竞争情况逐渐升级。且锁的升级不可逆,只能升级,不能降级。这是为了提高获得锁和释放锁的效率
无锁状态 -> 偏向锁状态 -> 轻量级锁状态 -> 重量级锁状态
偏向锁
HotSport作者发现,锁在大多情况下多为一个线程获得,不存在多线程竞争,所以基于这样的情况下,原来的锁的获得就略显复杂。为了解决这一问题引入了偏向锁来降低获得锁的代价。
具体的操作流程为:
- 会在栈帧和对象头的锁记录里存放偏向线程的ID,然后该线程在进入和退出同步块时不需要使用CAS操作来进行加锁或者解锁。
- 在加锁或者解锁时需要检测偏向锁是否储存当前线程的ID,如果没有则再检测MarkWord里是否为偏向锁的标识是否为1,如果不为1则使用CAS去竞争锁,如果为1则去尝试使用CAS把对象头的偏向锁指向当前线程。
偏向锁的撤销
偏向锁采取的政策为等到竞争出现才释放锁的机制,所以当其他线程去竞争锁时,拥有偏向锁的线程才会释放锁。
- 要等到全局安全点(没有正在执行的字节码)。
- 然后暂停拥有偏向锁的线程。
- 检测持有偏向锁的线程是否存活。
- 如果不处于活动状态则将对象头设置为无锁模式。
- 如果依旧存活,拥有偏向锁的栈会被执行,遍历偏向对象的锁记录,要么把栈中的锁记录和对象头的Mark Word要么重新偏向于其他线程,要么恢复到无锁状态或者标记对象不适合作为偏向锁。
关闭偏向锁
偏向锁在java6和java7里是默认启用的,但是它存在程序启动后的几秒延迟,可以使用JVM参数来关闭偏向锁,然后程序就会进入轻量级锁状态。