读懂这篇文章,带你快速理解synchronized实现原理及锁升级过程,干货满满

在这里插入图片描述

1,用法

synchronized可用来给对象和方法或者代码块加锁,当它锁定一个方法或者一个代码块的时候,同一时刻最多只有一个线程执行这段代码。
synchronized的三种方式:
1,作用于实例方法,当前实例枷锁。进入同步代码前要获得当前实例的锁。
2,作用于静态方法,当前类枷锁。进去同步代码前要获得当前类对象的锁。
3,作用于代码块,对括号里配置的对象加锁。

2,实现原理

  • java对象头
    synchronized用的锁存在对象头里,Java对象头里的MarkWord默认存储对象的HashCode,分代年龄和锁标记位。再运行期间,Mark Word里存储的数据会随着锁标志位的变化而变化。32位Jvm的MarkWord可能变化存储为一下5种数据。
    在这里插入图片描述
    锁一共是四种状态,级别从高到低依次是:无锁状态,偏向锁状态,轻量级锁状态和重量级锁状态。这几个状态随着竞争情况逐渐升级。为了提高获得锁和释放锁的效率,锁可以升级但是不能降级,意味着偏向锁升级为轻量级锁后不能降级为偏向锁

  • 偏向锁
    当一个线程访问同步代码块时,会在对象头和栈帧的锁记录里存储偏向的线程ID,以后该线程再进入和退出同步代码块时不需要进行CAS操作加锁和解锁,只需要测试Mark Word里线程ID是否为当前线程。如果测试成功,表示线程已经获得了锁。如果测试失败,则需要判断偏向锁的标识。如果标识被设置为0(表示当前无锁状态),则使用CAS竞争锁;如果标识设置成1(表示当前时偏向锁状态),则尝试使用CAS将对象头的偏向锁指向当前线程,触发偏向锁的撤销。偏向锁只有在竞争出现才会释放锁。当其他线程尝试竞争偏向锁时,程序到达全局安全点后(没有正在执行的代码),它会查看Java对象头中记录的线程是否存活,如果没有存活,那么锁对象被重置为无锁状态,其它线程可以竞争将其设置为偏向锁;如果存活,那么立刻查找该线程的栈帧信息,如果还是需要继续持有这个锁对象,那么暂停当前线程,撤销偏向锁,升级为轻量级锁,如果线程1不再使用该锁对象,那么将锁对象状态设为无锁状态,重新偏向新的线程。

  • 轻量级锁
    线程在执行同步块之前,JVM会先在当前线程的栈帧中创建用于存储锁记录的空间,并将对象头的MarkWord复制到锁记录中,即Displaced Mark Word。然后线程会尝试使用CAS将对象头中的Mark Word替换为指向锁记录的指针。如果成功,当前线程获得锁。如果失败,表示其他线程在竞争锁,当前线程使用自旋来获取锁。当自旋次数达到一定次数时,锁就会升级为重量级锁。
    在这里插入图片描述
    轻量级锁解锁时,会使用CAS操作将Displaced Mark Word替换回到对象头,如果成功,表示没有竞争发生。如果失败,表示当前锁存在竞争,锁已经被升级为重量级锁,则会释放锁并唤醒等待的线程。
    在这里插入图片描述

锁的优缺点比较

偏向锁:
优点:加锁解锁不需要额外的消耗,和执行非同步方法比仅存在纳秒级的差距
缺点:如果线程间存在锁竞争,会带来额外的锁撤销的消耗
适用场景:适合只有一个线程访问同步快的场景

轻量级锁:
优点:竞争的线程不会阻塞,提高程序的响应速度
缺点:如果始终得不到锁竞争的线程使用自旋会消耗CPU
适用场景:追求响应时间 同步块执行速度非常快

重量级锁:
优点:线程竞争不适用自旋 不会消耗CPU
缺点:线程阻塞 响应时间缓慢
适用场景:追求吞吐量 同步块执行时间长

对于synchronized加锁的完整过程描述:

  1. 检查Mark Word里存放的是否是自身的ThreadId,如果是,表示当前线程处于偏向锁,无需加锁就可获取临界资源
  2. 如果不是自身的ThreadId,锁升级,使用CAS来进行切换,新的线程根据MarkWord里现有的ThreadId,通知之前线程暂停,之前线程把MarkWord的内容设置为空
  3. 两个线程都把对象的HashCode复制到自己新建的用于存储锁的记录空间,接着开始通过CAS操作把共享对象的MarkWord的内容修改为自己新建的记录空间的地址的方式竞争MarkWord
  4. 成功执行CAS的获得资源,失败的进入自旋
  5. 自旋在线程在自旋过程中,成功获得资源则整个状态依然处于轻量级的锁状态
    如果自旋失败进入重量级锁的状态,自旋的线程进行阻塞,等待之前的线程完成并唤醒自己

参考:https://blog.csdn.net/qq_26222859/article/details/53786134

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值