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核心技术面试精讲
登录|注册

第15讲 | synchronized和ReentrantLock有什么区别呢?

杨晓峰 2018-06-07
从今天开始,我们将进入 Java 并发学习阶段。软件并发已经成为现代软件开发的基础能力,而 Java 精心设计的高效并发机制,正是构建大规模应用的基础之一,所以考察并发基本功也成为各个公司面试 Java 工程师的必选项。
今天我要问你的问题是, synchronized 和 ReentrantLock 有什么区别?有人说 synchronized 最慢,这话靠谱吗?
取消
完成
0/1000字
划线
笔记
复制
© 版权归极客邦科技所有,未经许可不得传播售卖。 页面已增加防盗追踪,如有侵权极客邦将依法追究其法律责任。
该试读文章来自付费专栏《Java核心技术面试精讲》,如需阅读全部文章,
请订阅文章所属专栏。
立即订阅
登录 后留言

精选留言(62)

  • 公号-代码荣耀
    ReentrantLock是Lock的实现类,是一个互斥的同步器,在多线程高竞争条件下,ReentrantLock比synchronized有更加优异的性能表现。

    1 用法比较
    Lock使用起来比较灵活,但是必须有释放锁的配合动作
    Lock必须手动获取与释放锁,而synchronized不需要手动释放和开启锁
    Lock只适用于代码块锁,而synchronized可用于修饰方法、代码块等


    2 特性比较
    ReentrantLock的优势体现在:
    具备尝试非阻塞地获取锁的特性:当前线程尝试获取锁,如果这一时刻锁没有被其他线程获取到,则成功获取并持有锁
    能被中断地获取锁的特性:与synchronized不同,获取到锁的线程能够响应中断,当获取到锁的线程被中断时,中断异常将会被抛出,同时锁会被释放
    超时获取锁的特性:在指定的时间范围内获取锁;如果截止时间到了仍然无法获取锁,则返回

    3 注意事项
    在使用ReentrantLock类的时,一定要注意三点:
    在finally中释放锁,目的是保证在获取锁之后,最终能够被释放
    不要将获取锁的过程写在try块内,因为如果在获取锁时发生了异常,异常抛出的同时,也会导致锁无故被释放。
    ReentrantLock提供了一个newCondition的方法,以便用户在同一锁的情况下可以根据不同的情况执行等待或唤醒的动作。
    2018-06-07
    126
  • 逐梦之音
    一直在研究JUC方面的。所有的Lock都是基于AQS来实现了。AQS和Condition各自维护了不同的队列,在使用lock和condition的时候,其实就是两个队列的互相移动。如果我们想自定义一个同步器,可以实现AQS。它提供了获取共享锁和互斥锁的方式,都是基于对state操作而言的。ReentranLock这个是可重入的。其实要弄明白它为啥可重入的呢,咋实现的呢。其实它内部自定义了同步器Sync,这个又实现了AQS,同时又实现了AOS,而后者就提供了一种互斥锁持有的方式。其实就是每次获取锁的时候,看下当前维护的那个线程和当前请求的线程是否一样,一样就可重入了。

    作者回复: 正解

    2018-06-07
    2
    65
  • BY
    要是早看到这篇文章,我上次面试就过了。。

    作者回复: 加油

    2018-06-07
    24
  • Jerry银银
    先说说点学习感受:
    并发领域的知识点很多也很散,并且知识点之间交错的。比如:synchronized,这个小小的关键字,能够彻底理解它,需要的知识储备有:基本使用场景、对锁的理解、对线程安全的理解、对同步语义的理解、对JMM的理解等等。有时候,一个知识点暂时做不到透彻理解,可能是正常的,需要再继续学习其它的知识点,等到一定时候,回过头来重新学习,会有一种柳暗花明又一村的感觉。我想,这也可能是老师提到的:并发领域相关知识的准备,需要点耐心。

    再说说这篇专栏:
    这篇专栏,在知识扩展部分,我觉得结构不是太清晰。我读了很多遍之后,还是有这种感觉:文章讲了很多东西,但是我却很难说出文章的主题。
    为此,我自己总结了一下知识扩展部分的主线:
    1. 进入并发领域,首先需要理解什么是线程安全,为什么会存在线程不安全,又为什么需要线程安全。这个知识点可参考《Java并发编程实践》,并且我也认为对于线程安全的讲解,这本书堪称权威;
    2. 老师在讲解线程安全这个点的时候,顺其自然地使用了synchronized和ReentrantLock来保证线程安全(即:Java提供的锁机制)同时,老师也稍微讲解了一下synchronized和ReentrantLock的使用和区别;
    3. 最后,老师举了一个ReentrantLock的典型使用场景:ArrayBlockingQueue。ArrayBlockingQueue使用ReentrantLock来实现加锁机制,保证队列的安全读取,并且使用Condition来实现队列阻塞的条件判断和读写端唤醒,特别提一句:具体的实现代码是相当的优雅!

    作者回复: 非常感谢反馈

    2019-02-01
    14
  • Kyle
    最近刚看完《Java 并发编程实战》,所以今天看这篇文章觉得丝毫不费力气。开始觉得,极客时间上老师讲的内容毕竟篇幅有限,更多的还是需要我们课后去深入钻研。希望老师以后讲完课也能够适当提供些参考书目,谢谢。

    作者回复: 后面会对实现做些源码分析,其实还有各种不同的锁...

    2018-06-07
    12
  • Daydayup
    我用过读写分离锁,读锁保证速度,写锁保证安全问题。再入锁还是挺好用的。老师写的很棒,学到不少知识。感谢

    作者回复: 非常感谢

    2018-06-13
    7
  • 灰飞灰猪不会灰飞.烟灭
    ReentrantLock 加锁的时候通过cas算法,将线程对象放到一个双向链表中,然后每次取出链表中的头节点,看这个节点是否和当前线程相等。是否相等比较的是线程的ID。
    老师我理解的对不对啊?

    作者回复: 嗯,并发库里都是靠自己的synchronizer

    2018-06-07
    6
  • 猪哥灰
    为了研究java的并发,我先把考研时候的操作系统教材拿出来再仔细研读一下,可见基础之重要性,而不管是什么语言,万变不离其宗
    2018-06-29
    5
  • 木瓜芒果
    杨老师,您好,synchronized在低竞争场景下可能优于retrantlock,这里的什么程度算是低竞争场景呢?

    作者回复: 这个精确的标准我还真不知道,我觉得可以这么理解:如果大部分情况,每个线程都不需要真的获取锁,就是低竞争;反之,大部分都要获取锁才能正常工作,就是高竞争

    2018-06-19
    5
  • xinfangke
    老师 问你个问题 在spring中 如果标注一个方法的事务隔离级别为序列化 而数据库的隔离级别是默认的隔离级别 此时此方法中的更新 插入语句是如何执行的?能保证并发不出错吗

    作者回复: 这个我没用过,哪位读者熟悉?

    2018-06-08
    5
  • 加载中……
    看到留言区,有个同学问:new ReentrantLock()能不能写到里面,我看了回复,不是很认同,不知道到对不对。其实:new lock和lock api的调用得写到try外面,写到里面会有问题,如下:
    lock() api 可能会抛出异常,如果放到try里面,在finally里面unlock会再抛出异常(因为当前状态不对),这个时候 "解锁异常"会隐藏"加锁异常",也就是异常堆栈只有“解锁异常”没有"加锁异常",而这样会误导程序员吧?,模拟代码如下:
    try {
                //如果lock在try里,且lock抛出异常
                throw new RuntimeException("加锁异常");
            } finally {
                //调用unlock如果lock没有获取到锁会抛出异常,这个在堆栈会隐藏“加锁异常”
                throw new RuntimeException("解锁异常");
            }
    2019-02-25
    3
  • Neil
    可以理解为synchronized是悲观锁 另一个是乐观锁

    作者回复: 基本如此,乐观、悲观是两种不同的处理策略

    2019-01-07
    3
  • Miaozhe
    杨老师,问个问题,看网上有说Condition的await和signal方法,等同于Object的wait和notify,看了一下源码,没有直接的关系。
    ReentractLock是基于双向链表的对接和CAS实现的,感觉比Object增加了很多逻辑,怎么会比Synchronized效率高?有疑惑。

    作者回复: 你看到的很对,如果从单个线程做的事来看,也许并没有优势,不管是空间还是时间,但ReentrantLock这种所谓cas,或者叫lock-free,方式的好处,在于高竞争情况的扩展性,而原来那种频繁的上下文切换则会导致吞吐量迅速下降

    2018-06-12
    3
  • 李飞
    老师,可以问您一个课外题吗。具备怎样的能力才算是java高级开发
    2018-06-08
    1
    3
  • sunlight001
    老师这里说的低并发和高并发的场景,大致什么数量级的算低并发?我们做管理系统中用到锁的情况基本都算低并发吧

    作者回复: 还真不知道有没有具体标准,但从逻辑上,低业务量不一定是“低竞争”,可能因为程序设计原因变成了“高竞争”

    2018-06-07
    3
  • PP丶
    ReentrantLock是Lock的实现类,是一个互斥的同步器,在多线程高竞争条件下,ReentrantLock比synchronized有更加优异的性能表现。

    1 用法比较
    Lock使用起来比较灵活,但是必须有释放锁的配合动作
    Lock必须手动获取与释放锁,而synchronized不需要手动释放和开启锁
    Lock只适用于代码块锁,而synchronized可用于修饰方法、代码块等


    2 特性比较
    ReentrantLock的优势体现在:
    具备尝试非阻塞地获取锁的特性:当前线程尝试获取锁,如果这一时刻锁没有被其他线程获取到,则成功获取并持有锁
    能被中断地获取锁的特性:与synchronized不同,获取到锁的线程能够响应中断,当获取到锁的线程被中断时,中断异常将会被抛出,同时锁会被释放
    超时获取锁的特性:在指定的时间范围内获取锁;如果截止时间到了仍然无法获取锁,则返回

    3 注意事项
    在使用ReentrantLock类的时,一定要注意三点:
    在finally中释放锁,目的是保证在获取锁之后,最终能够被释放
    不要将获取锁的过程写在try块内,因为如果在获取锁时发生了异常,异常抛出的同时,也会导致锁无故被释放。
    ReentrantLock提供了一个newCondition的方法,以便用户在同一锁的情况下可以根据不同的情况执行等待或唤醒的动作。
    2018-08-14
    2
  • clz1341521
    所有的Lock都是基于AQS来实现了。AQS和Condition各自维护了不同的队列,在使用lock和condition的时候,其实就是两个队列的互相移动。如果我们想自定义一个同步器,可以实现AQS。它提供了获取共享锁和互斥锁的方式,都是基于对state操作而言的。ReentranLock这个是可重入的。其实要弄明白它为啥可重入的呢,咋实现的呢。其实它内部自定义了同步器Sync,这个又实现了AQS,同时又实现了AOS,而后者就提供了一种互斥锁持有的方式。其实就是每次获取锁的时候,看下当前维护的那个线程和当前请求的线程是否一样,一样就可重入了。
    杨老师,我一直是这样用rerentlock的,在使用的类中定义一个static的rerentlock,然后哪个方法中需要用到再 try 中 xx.lock,然后finally中xx.unlock。这样用有没有问题?
    2018-08-05
    2
  • leleba
    这里怎么没有精彩的留言了呢?很难吗,反正我觉得难,但必须要学
    2018-11-02
    1
  • 时间总漫不经心
    老师,jmm什么时候将工作内存的值写入到主内存中呢?

    作者回复: volatile读写、同步块这种

    2018-08-10
    1
  • Daydayup
    我用过读写分离锁,读锁保证速度,写锁保证安全问题。再入锁还是挺好用的。老师写的很棒,学到不少知识。感谢
    2018-06-13
    1
收起评论
62
返回
顶部