java synchronized 锁升级

在JDK1.6之后,synchronized引入了无锁、偏向锁、轻量锁、重量锁的不可逆状态升级过程,以提高锁的获取和释放效率。

四种状态锁对象的对象头以及升级过程

java synchronized 锁升级_第1张图片

  1. 最开始锁对象处于无锁状态,当初次执行到synchronized代码块的时候,锁对象变为偏向锁。此时通过cas修改偏向锁标志为1以及mark word改为偏向线程id
  2. 之后当锁对象被其他线程所访问,升级到轻量级锁,其他线程通过自旋的方式获取锁。此时锁标志位改为00,锁对象头除锁标志外的62bit由竞争成功线程栈记录地址指针所替代。
  3. 最后当某个线程自旋次数超过限度(默认为10),那么就由该线程将锁升级为重量级锁,未占有锁对象的线程进入等待队列。此时锁标志位改为10,mark word改为占有该锁的线程对该锁对象对应的重量级锁Monitor的指针

无锁

无锁是指不对资源进行锁定,所有线程都能访问到资源,但只有一个线程能够修改成功。

偏向锁

为什么引入偏向锁

HotSpot作者研究发现,多数情况下其实并不存在锁竞争,常常是一个线程多此获得同一个锁,所以为了降低锁获取代价,于是引入。

也可以通过虚拟机参数-XX:-UseBiasedLocking = false取消偏向锁

获取

线程B比较自己的threadId以及锁对象头threadId是否一致,若一致,则直接获取锁对象,无需使用cas加解锁。若不一致,则查看锁对象头中占有线程A是否存活,若不存活,则未占有线程竞争。若存活,进一步查看占有线程A是否需要继续持有,若需要继续持有,则暂停该线程,升级为轻量级锁,若不继续持有,为占有线程竞争。

轻量级锁

为什么引入

轻量锁考虑的是竞争锁线程不多而且持有锁时间也不长的情况。

重量级锁

重量级锁锁对象头引入了Monitor对象或者说同步工具。

Monitor是线程私有的数据结构,每一个线程都有一个monitor record列表,线程中每一个锁住的对象都有对应的monitor,并且在monitor中有一个owner字段标识着拥有该锁线程。

monitor线程同步是依赖于底层操作系统的mutex lock来实现同步。

Ref

  1. https://segmentfault.com/a/1190000022904663
  2. https://blog.csdn.net/tongdanping/article/details/79647337

你可能感兴趣的:(java,多线程)