Java 核心技术面试精讲
杨晓峰
前 Oracle 首席工程师
125942 人已学习
新⼈⾸单¥59
登录后,你可以任选4讲全文学习
课程目录
已完结/共 44 讲
Java 核心技术面试精讲
15
15
1.0x
00:00/00:00
登录|注册

第16讲 | synchronized底层如何实现?什么是锁的升级、降级?

重量级锁
轻量级锁
偏斜锁
自旋锁的作用和使用场景
StampedLock
ReadWriteLock
ObjectSynchronizer类
fast_enter和slow_enter方法
UseBiasedLocking检查
Runtime相关功能实现
偏斜锁、轻量级锁、重量级锁的切换
JVM优化synchronized运行的机制
三种不同的Monitor实现
Java 6之前的实现
依赖操作系统内部的互斥锁
一课一练
其他锁类型
源码层面分析
锁的升级、降级
现代JDK中的改进
Monitor对象
synchronized底层实现

该思维导图由 AI 生成,仅供参考

我在上一讲对比和分析了 synchronized 和 ReentrantLock,算是专栏进入并发编程阶段的热身,相信你已经对线程安全,以及如何使用基本的同步机制有了基础,今天我们将深入了解 synchronize 底层机制,分析其他锁实现和应用场景。
今天我要问你的问题是 ,synchronized 底层如何实现?什么是锁的升级、降级?
确认放弃笔记?
放弃后所记笔记将不保留。
新功能上线,你的历史笔记已初始化为私密笔记,是否一键批量公开?
批量公开的笔记不会为你同步至部落
公开
同步至部落
取消
完成
0/2000
荧光笔
直线
曲线
笔记
复制
AI
  • 深入了解
  • 翻译
    • 英语
    • 中文简体
    • 中文繁体
    • 法语
    • 德语
    • 日语
    • 韩语
    • 俄语
    • 西班牙语
    • 阿拉伯语
  • 解释
  • 总结

Java并发编程中的锁机制是至关重要的内容,本文深入探讨了synchronized的底层实现以及现代JDK中提供的偏斜锁、轻量级锁和重量级锁等三种Monitor实现。文章详细解释了锁的升级、降级机制,并介绍了Java并发包中的其他锁类型,如读写锁和StampedLock,并分析了它们在实际应用中的优劣势。通过示例代码,读者可以更好地理解这些锁的使用方法。此外,文章还涉及了Java并发包内的各种同步工具,不仅仅是各种Lock,还包括其他框架。对于对Java底层源码感兴趣的读者来说,本文是一个重要的切入点,可以帮助他们更好地掌握Java内置锁实现的知识,为并发编程打下坚实的基础。

仅可试看部分内容,如需阅读全部内容,请付费购买文章所属专栏
《Java 核心技术面试精讲》
新⼈⾸单¥59
立即购买
登录 后留言

全部留言(70)

  • 最新
  • 精选
  • 公号-技术夜未眠
    自旋锁:竞争锁的失败的线程,并不会真实的在操作系统层面挂起等待,而是JVM会让线程做几个空循环(基于预测在不久的将来就能获得),在经过若干次循环后,如果可以获得锁,那么进入临界区,如果还不能获得锁,才会真实的将线程在操作系统层面进行挂起。 适用场景:自旋锁可以减少线程的阻塞,这对于锁竞争不激烈,且占用锁时间非常短的代码块来说,有较大的性能提升,因为自旋的消耗会小于线程阻塞挂起操作的消耗。 如果锁的竞争激烈,或者持有锁的线程需要长时间占用锁执行同步块,就不适合使用自旋锁了,因为自旋锁在获取锁前一直都是占用cpu做无用功,线程自旋的消耗大于线程阻塞挂起操作的消耗,造成cpu的浪费。

    作者回复: 不错,自旋是种乐观情况的优化

    2018-06-12
    2
    189
  • yearning
    这次原理真的看了很久,一直鼓劲自己,看不懂就是说明自己有突破。 下面看了并发编程对于自旋锁的了解,同时更深刻理解同步锁的性能。 自旋锁采用让当前线程不停循环体内执行实现,当循环条件被其他线程改变时,才能进入临界区。 由于自旋锁只是将当前线程不停执行循环体,不进行线程状态的改变,所以响应会更快。但当线程不停增加时,性能下降明显。 线程竞争不激烈,并且保持锁的时间段。适合使用自旋锁。 为什么会提出自旋锁,因为互斥锁,在线程的睡眠和唤醒都是复杂而昂贵的操作,需要大量的CPU指令。如果互斥仅仅被锁住是一小段时间, 用来进行线程休眠和唤醒的操作时间比睡眠时间还长,更有可能比不上不断自旋锁上轮询的时间长。 当然自旋锁被持有的时间更长,其他尝试获取自旋锁的线程会一直轮询自旋锁的状态。这将十分浪费CPU。 在单核CPU上,自旋锁是无用,因为当自旋锁尝试获取锁不成功会一直尝试,这会一直占用CPU,其他线程不可能运行, 同时由于其他线程无法运行,所以当前线程无法释放锁。 混合型互斥锁, 在多核系统上起初表现的像自旋锁一样, 如果一个线程不能获取互斥锁, 它不会马上被切换为休眠状态,在一段时间依然无法获取锁,进行睡眠状态。 混合型自旋锁,起初表现的和正常自旋锁一样,如果无法获取互斥锁,它也许会放弃该线程的执行,并允许其他线程执行。 切记,自旋锁只有在多核CPU上有效果,单核毫无效果,只是浪费时间。 以上基本参考来源于: http://ifeve.com/java_lock_see1/ http://ifeve.com/practice-of-using-spinlock-instead-of-mutex/

    作者回复: 很不错总结

    2018-06-12
    5
    81
  • jacy
    看了大家对自旋锁的评论,我的收获如下: 1.基于乐观情况下推荐使用,即锁竞争不强,锁等待时间不长的情况下推荐使用 2.单cpu无效,因为基于cas的轮询会占用cpu,导致无法做线程切换 3.轮询不产生上下文切换,如果可估计到睡眠的时间很长,用互斥锁更好

    作者回复: 不错

    2018-06-19
    4
    36
  • sunlight001
    自旋锁是尝试获取锁的线程不会立即阻塞,采用循环的方式去获取锁,好处是减少了上下文切换,缺点是消耗cpu

    作者回复: 不错

    2018-06-12
    32
  • Miaozhe
    杨老师,偏斜锁有什么作用?还是没有看明白,如果只是被一个线程获取,那么锁还有什么意义? 另外,如果我有两个线程明确定义调用同一个对象的Synchronized块,JVM默认肯定先使用偏斜锁,之后在升级到轻量级所,必须经过撤销Revoke吗?编译的时候不会自动优化?

    作者回复: 我理解偏斜锁就是为了优化那些没有并发却写了同步逻辑的代码;javac编译时能判断的是有限的;一旦有另外线程想获取,就会revoke,而且开销明显

    2018-06-12
    3
    24
  • 陈一嘉
    自旋锁 for(;;)结合cas确保线程获取取锁

    作者回复: 差不多

    2018-06-12
    13
  • 灰飞灰猪不会灰飞.烟灭
    老师 AQS就不涉及用户态和内核态的切换了 对吧?

    作者回复: 我理解是,cas是基于特定指令

    2018-06-12
    8
  • stephen chow
    StampLock是先试着读吧?你写的先试着修改。。

    作者回复: 嗯,是有点写跑偏了,看上下文倒也能理解,谢谢指出

    2018-10-01
    7
  • Miaozhe
    关于自旋转锁不适合单核CPU的问题,下来查找了一下资料: 1.JVM在操作系统中是作为一个进程存在,但是OS一般都将将线程作为最小调度单位,进程是资源分配的最小单位。这就是说进程是不活动的,只是作为线程的容器,那么Java的线程是在JVM进程中,也被CPU调度。 2.单核CPU使用多线程时,一个线程被CPU执行,其它处于等待轮巡状态。 3.为什么多线程跑在单核CPU上也比较快呢?是由于这种线程还有其它IO操作(File,Socket),可以跟CPU运算并行。 4.结论,根据前面3点的分析,与自旋转锁的优点冲突:线程竞争不激烈,占用锁时间短。

    作者回复: 自旋是基于乐观假设,就是等待中锁被释放了,单核cpu就自己占着cpu,别人没机会让

    2018-06-13
    5
  • Miaozhe
    杨老师,看到有回复说自旋锁在单核CPU上是无用,感觉这个理论不准确,因为Java多线程在很早时候单核CPC的PC上就能运行,计算机原理中也介绍,控制器会轮巡各个进程或线程。而且多线程是运行在JVM上,跟物理机没有很直接的关系吧?

    作者回复: 已回复,我也认为单核无用

    2018-06-13
    5
收起评论
显示
设置
留言
70
收藏
沉浸
阅读
分享
手机端
快捷键
回顶部