面试题:解释一下synchronized的轻量级锁,锁膨胀、自旋优化、偏向锁

在Java中,synchronized 关键字用于实现线程同步和互斥访问共享资源。当多个线程尝试访问被synchronized修饰的代码块时,会对共享资源进行加锁,以保证线程安全。在JVM中,synchronized关键字的实现涉及不同层次的锁机制,包括轻量级锁、锁膨胀、自旋优化和偏向锁。

  • 轻量级锁(Lightweight Locking):

    • 轻量级锁的使用场景:如果一个对象虽然有多线程要加锁,但加锁的时间是错开的(也就是没有竞争),那么可以 使用轻量级锁来优化。
    • 轻量级锁是为了解决在无竞争情况下对锁的性能开销。当一个线程获取锁时,JVM会在对象的头部存储线程ID,标记为锁定状态。
    • 如果另一个线程尝试获取相同的锁,JVM会使用CAS(Compare and Swap)操作尝试获取锁。如果成功,表示获取到了轻量级锁。
    • 如果CAS操作失败,表示存在竞争,锁将膨胀为重量级锁。
  • 锁膨胀(Lock Coarsening):

    • 当线程在执行同步代码块时,如果发现有连续的多个synchronized块出现在同一段代码中,JVM会将它们合并为一个较大的同步块。
    • 这样可以减少加锁和释放锁的次数,提高性能。
  • 自旋优化(Spin Lock):

    • 自旋优化是指当线程尝试获取锁时,如果发现锁被其他线程持有,它不会立即阻塞,而是进行一段短暂的自旋等待。
    • 自旋等待期间,线程会忙等待(不会释放CPU),尝试获取锁的线程会不断自旋检查锁是否被释放。
    • 自旋等待的目的是期望持有锁的线程能够在短时间内释放锁,从而避免线程切换的开销。
  • 偏向锁(Biased Locking):

    • 偏向锁是为了在无竞争情况下减少锁的操作开销。在对象实例创建后,JVM会将锁的标记设置为偏向锁状态。
    • 当线程尝试获取锁时,JVM会检查锁的标记,如果发现是偏向锁并且线程ID匹配,表示获取到锁。
    • 如果有其他线程尝试获取锁,则偏向锁会升级为轻量级锁。
    • 偏向锁的目的是为了提高无竞争情况下的性能,避免加锁和解锁的开销。

轻量级锁和偏向锁区别?

  • 轻量级锁(Lightweight Lock):

    • 轻量级锁适用于存在短时间内的竞争情况下。当线程尝试获取锁时,JVM会将对象头部中的锁信息设置为轻量级锁状态。
    • 如果同一对象的锁状态是轻量级锁,表示只有一个线程持有锁。此时,线程使用CAS(Compare and Swap)操作来尝试获取锁。
    • 如果CAS操作成功,表示获取到了轻量级锁,可以继续执行同步代码块。
    • 如果CAS操作失败,表示存在竞争,轻量级锁会膨胀为重量级锁,即通过互斥量来实现锁的操作。
  • 偏向锁(Biased Lock):

    • 偏向锁适用于无竞争的情况下,即一个线程多次获取同一个锁的情况。偏向锁的目的是在无竞争的情况下减少锁的操作开销。
    • 当一个线程第一次尝试获取锁时,JVM会将锁的标记设置为偏向锁状态,并将线程ID记录在对象头中。
    • 轻量级锁在没有竞争时(就自己这个线程),每次重入仍然需要执行 CAS 操作。
    • 当该线程再次获取锁时,JVM会检查锁的标记和线程ID是否匹配,如果匹配,表示获取到了偏向锁,无需进行同步操作。
    • 如果有其他线程尝试获取同一把锁,偏向锁会被撤销,升级为轻量级锁或重量级锁。
  • 区别总结:

    • 轻量级锁适用于短时间内的竞争情况下,通过CAS操作进行快速的加锁和解锁,避免使用互斥量的开销。
    • 偏向锁适用于无竞争的情况下,提供了在单线程执行时的高性能。当存在竞争时,偏向锁会被撤销。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值