Java核心技术面试精讲
杨晓峰
前Oracle首席工程师
立即订阅
43250 人已学习
课程目录
已完结 43 讲
0/4登录后,你可以任选4讲全文学习。
开篇词 (1讲)
开篇词 | 以面试题为切入点,有效提升你的Java内功
免费
模块一 Java基础 (14讲)
第1讲 | 谈谈你对Java平台的理解?
第2讲 | Exception和Error有什么区别?
第3讲 | 谈谈final、finally、 finalize有什么不同?
第4讲 | 强引用、软引用、弱引用、幻象引用有什么区别?
第5讲 | String、StringBuffer、StringBuilder有什么区别?
第6讲 | 动态代理是基于什么原理?
第7讲 | int和Integer有什么区别?
第8讲 | 对比Vector、ArrayList、LinkedList有何区别?
第9讲 | 对比Hashtable、HashMap、TreeMap有什么不同?
第10讲 | 如何保证集合是线程安全的? ConcurrentHashMap如何实现高效地线程安全?
第11讲 | Java提供了哪些IO方式? NIO如何实现多路复用?
第12讲 | Java有几种文件拷贝方式?哪一种最高效?
第13讲 | 谈谈接口和抽象类有什么区别?
第14讲 | 谈谈你知道的设计模式?
模块二 Java进阶 (16讲)
第15讲 | synchronized和ReentrantLock有什么区别呢?
第16讲 | synchronized底层如何实现?什么是锁的升级、降级?
第17讲 | 一个线程两次调用start()方法会出现什么情况?
第18讲 | 什么情况下Java程序会产生死锁?如何定位、修复?
第19讲 | Java并发包提供了哪些并发工具类?
第20讲 | 并发包中的ConcurrentLinkedQueue和LinkedBlockingQueue有什么区别?
第21讲 | Java并发类库提供的线程池有哪几种? 分别有什么特点?
第22讲 | AtomicInteger底层实现原理是什么?如何在自己的产品代码中应用CAS操作?
第23讲 | 请介绍类加载过程,什么是双亲委派模型?
第24讲 | 有哪些方法可以在运行时动态生成一个Java类?
第25讲 | 谈谈JVM内存区域的划分,哪些区域可能发生OutOfMemoryError?
第26讲 | 如何监控和诊断JVM堆内和堆外内存使用?
第27讲 | Java常见的垃圾收集器有哪些?
第28讲 | 谈谈你的GC调优思路?
第29讲 | Java内存模型中的happen-before是什么?
第30讲 | Java程序运行在Docker等容器环境有哪些新问题?
模块三 Java安全基础 (2讲)
第31讲 | 你了解Java应用开发中的注入攻击吗?
第32讲 | 如何写出安全的Java代码?
模块四 Java性能基础 (3讲)
第33讲 | 后台服务出现明显“变慢”,谈谈你的诊断思路?
第34讲 | 有人说“Lambda能让Java程序慢30倍”,你怎么看?
第35讲 | JVM优化Java代码时都做了什么?
模块5 Java应用开发扩展 (4讲)
第36讲 | 谈谈MySQL支持的事务隔离级别,以及悲观锁和乐观锁的原理和应用场景?
第37讲 | 谈谈Spring Bean的生命周期和作用域?
第38讲 | 对比Java标准NIO类库,你知道Netty是如何实现更高性能的吗?
第39讲 | 谈谈常用的分布式ID的设计方案?Snowflake是否受冬令时切换影响?
周末福利 (2讲)
周末福利 | 谈谈我对Java学习和面试的看法
周末福利 | 一份Java工程师必读书单
结束语 (1讲)
结束语 | 技术没有终点
Java核心技术面试精讲
登录|注册

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

杨晓峰 2018-06-12
我在上一讲对比和分析了 synchronized 和 ReentrantLock,算是专栏进入并发编程阶段的热身,相信你已经对线程安全,以及如何使用基本的同步机制有了基础,今天我们将深入了解 synchronize 底层机制,分析其他锁实现和应用场景。
今天我要问你的问题是 ,synchronized 底层如何实现?什么是锁的升级、降级?
取消
完成
0/1000字
划线
笔记
复制
© 版权归极客邦科技所有,未经许可不得传播售卖。 页面已增加防盗追踪,如有侵权极客邦将依法追究其法律责任。
该试读文章来自付费专栏《Java核心技术面试精讲》,如需阅读全部文章,
请订阅文章所属专栏。
立即订阅
登录 后留言

精选留言(56)

  • 公号-代码荣耀
    自旋锁:竞争锁的失败的线程,并不会真实的在操作系统层面挂起等待,而是JVM会让线程做几个空循环(基于预测在不久的将来就能获得),在经过若干次循环后,如果可以获得锁,那么进入临界区,如果还不能获得锁,才会真实的将线程在操作系统层面进行挂起。

    适用场景:自旋锁可以减少线程的阻塞,这对于锁竞争不激烈,且占用锁时间非常短的代码块来说,有较大的性能提升,因为自旋的消耗会小于线程阻塞挂起操作的消耗。
    如果锁的竞争激烈,或者持有锁的线程需要长时间占用锁执行同步块,就不适合使用自旋锁了,因为自旋锁在获取锁前一直都是占用cpu做无用功,线程自旋的消耗大于线程阻塞挂起操作的消耗,造成cpu的浪费。

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

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

    作者回复: 不错

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

    作者回复: 不错

    2018-06-12
    17
  • Roysatm

    1.synchronized锁,可分为偏向锁、轻量级锁、重量级锁。在jvm没有显示关闭偏向锁的情况下,初始状态时默认是偏向锁时,
    线程请求先通过CAS替换mark word中threadId,如果替换成功则该线程持有当前锁。如果替换失败,锁会升级为轻量级锁,
    线程请求会尝试CAS替换mark word中指向栈中锁记录的指针,如果替换成功则该线程持有当前锁。
    如果替换失败,当前线程会自旋一定次数,继续尝试获取CAS替换,如果超过一定自旋次数,锁升级为重量级锁。

    synchronized锁是调用系统内核互斥锁实现的,线程在获取synchronized锁失败后,也会进入一个等待获取锁队列中(系统内核实现的),
    线程会由运行态切换到阻塞态,让出CPU,待其他线程释放锁后唤醒它。

    synchronize锁重(1.6之后jvm有优化)就是重在两点,一是调用内核互斥锁实现,二是线程获取锁失败会变成阻塞态,让出CPU,等待唤醒(有一定的上下文切换)
    2019-02-17
    8
  • 黑子
    自旋锁 for(;;)结合cas确保线程获取取锁

    作者回复: 差不多

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

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

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

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

    2018-06-12
    4
  • 苦行僧
    轻量级锁和重量级锁没有详细说明和区别,仅从名字不好区别
    2019-02-18
    3
  • stephen chow
    StampLock是先试着读吧?你写的先试着修改。。

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

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

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

    2018-06-13
    3
  • Jerry银银
    『其逻辑是先试着修改,然后通过 validate 方法确认是否...』
    这里面先试着修改写错了,小编帮忙改下吧,应该是:『其逻辑是先试着读,然后....』 我看到留言中,有其它同学早就提出了,但是一直没有被修正。。。。

    作者回复: 谢谢指出

    2019-02-02
    2
  • 刘杰
    偏斜锁和轻量级锁的区别不是很清晰
    2018-07-12
    2
  • 随心而至
    AtomicInteger中使用的自旋spin, 其实就是不断尝试,直到CAS成功。
    public final int getAndUpdate(IntUnaryOperator updateFunction) {
            int prev, next;
            do {
                prev = get();
                next = updateFunction.applyAsInt(prev);
            } while (!compareAndSet(prev, next));
            return prev;
        }
    2019-09-18
    1
  • 张天屹
    自旋锁我理解了,但是没用过,请问其对于Java来说是jdk提供的api还是JVM层面的实现,还是OS层面的实现呢?
    2019-04-01
    1
  • (💐亮亮💐)
    自旋锁失败后,不是进入同步等待队列吗?
    2018-08-22
    1
  • clz1341521
    自旋锁是一种乐观优化
    自旋锁:竞争锁的失败的线程,并不会真实的在操作系统层面挂起等待,而是JVM会让线程做几个空循环(基于预测在不久的将来就能获得),在经过若干次循环后,如果可以获得锁,那么进入临界区,如果还不能获得锁,才会真实的将线程在操作系统层面进行挂起。

    适用场景:自旋锁可以减少线程的阻塞,这对于锁竞争不激烈,且占用锁时间非常短的代码块来说,有较大的性能提升,因为自旋的消耗会小于线程阻塞挂起操作的消耗。
    2018-08-05
    1
  • gesanri
    我有一个疑问,最后这个stampedlock的例子,access方法中,调用读乐观锁之后直接就进行read操作,但这个时候不知道validate的结果,如果validate为false,还要再read一次,为什么不先判断validate为true再read呢?是因为read这个操作太轻量级了吗?
    2018-08-04
    1
  • 苍天大树
    第一次回答问题哈,自旋锁就是当获取锁失败后,自己定时循环去获取锁,不进入休眠状态。这样的好处就是快,坏处就是消耗cpu
    2018-08-04
    1
  • Cui
    老师你好 心中一直有个疑问:synchronize和AQS的LockSupport同样起到阻塞线程的作用,这两者的区别是什么?能不能从实现原理和使用效果的角度说说?

    作者回复: LockSupport park是waiting,另一个是blocked;具体底层,马上一篇有说明

    2018-06-22
    1
收起评论
56
返回
顶部