大厂真题:

面试官非常喜欢抛出一个问题,让你自由发挥,看你能讲多深俗称"面试连珠炮"。

  • 请描述synchronized和reentrantlock的底层实现及重入的底层原理-百度阿里
  • 请描述锁的四种状态和升级过程-百度阿里
  • CAS的ABA问题如何解决-百度
  • 请谈一下AQS, 为什么AQS的底层是CAS + volatile -百度
  • 请谈一下你对Vvolatile的理解-美团阿里
  • volatile的可见性和禁止指令重排序是如何实现的-美团
  • CAS是什么-美团
  • 请描述-下对象的创建过程-美团顺丰
  • 对象在内存中的内存布局-美团顺丰
  • DCL单例为什么要加volatile -美团
  • 解释一下锁的四种状态-顺丰
  • Object o = new Object()在内存中占了多少字节? -顺丰
  • 请描述synchronized和ReentrantLock的异同-顺丰
  • 聊聊你对as-if- serial和happens- before语义的理解-京东
  • 你了解ThreadLocal吗? 你知道ThreadL ocal中如何解决内存泄漏问题吗? -京东阿里?
  • 请描述一下锁的分类以及JDK中的应用-阿里
  • 问:自旋锁一定比重量级锁效率高吗? -阿里
  • 打开偏向锁是否效率一定会提升?为什么?

怎么样?在不借助任何可以查询的工具,面对面的跟面试官交流,你能答出来吗?

很显然, 我觉得面对面试官的"面试连珠炮"、“刨根问底”,大多数人是很难答出来的,因为你会紧张,一开始会的东西都不会了。
说到底,还是因为自己学的不够扎实,在面试官面前比较犯虚,这些东西大家要慢慢来克服!

在此,就可以大家推荐一本武功秘籍,让大家修炼好自己的内功!

那就是,清华毕业扫地僧亲自编写的《多线程与高并发》,大家先来简单看一眼!!!

 

多线程与高并发

第一节:线程的基本概念

第一:基本的概念,从什么是线程开始

第二:JUC同步工具,就是各种同步锁

第三:同步容器

第四:线程池

第五:高频面试加分项的一些面试用的东西,包括纤程

第六:Disruptor,不知道有多少同学听说过这个框架的,这个框架它也是一个MQ框架(Message Queue)叫做消息队列,消息队列非常多,后面还会给大家讲Kafka、RabbitMQ,Redis等这些都是消息队列。Disruptor是目前大家公认的在单机环境上效率最高的、性能最快的MQ。

 

第二节:volatile与CAS

volatile

我们先来看这个volatile的概念,volatile它是什么意思,现在像大的互联网企业的面试,基本上volatile是必会的,有时候他也不会太问,认为你应该会,但是中小企业也就开始问这方面的问题。

我们来看一下这个小程序,写了一个方法啊,首先定义了一个变量布尔类型等于true,这里模拟的是一个服务器的操作,我的值为true你就给我不间断的运行,什么时候为false你再停止。 测试new Thread启动一个线程,调用m方法,睡了一秒,最后running等于false,运行方法他是不会停止的。 如果你要把volatile打开,那么结果就是启动程序一秒之后他就会m end停止。(volatile就是不停的追踪这个值,时刻看什么时候发生了变化)
CAS

cas号称是无锁优化,或者叫自旋。这个名字无所谓,理解它是干什么的就行,概念这个东西是人为了描述问题解决问题而定义出来的,所以怎么定义不是很重要,重点是在解决问题上我们通过Atomic类(原子的)。由于某一些特别常见的操作,老是来回的加锁,加锁的情况特别多,所以干脆java就提供了这些常见的操作这么一些个类,这些类的内部就自动带了锁,当然这些锁的实现并不是synchronized重量级锁,而是CAS的操作来实现的(号称无锁)。

我们来举例几个简单的例子,凡是以Atomic开头的都是用CAS这种操作来保证线程安全的这么一些个类。AtomicInteger的意思就是里面包了一个Int类型,这个int类型的自增 count++ 是线程安全的,还有拿值等等是线程安全的,由于我们在工作开发中经常性的有那种需求,一个值所有的线程共同访问它往上递增 ,所以jdk专门提供了这样的一些类。

第三节:Atomic类和线程同步新机制

今天,我们继续讲一个Atomic的问题,然后开始讲除synchronized之外的别的锁。在前面内容我们讲了synchronized、volatile、Atomic和CAS,Atomic我们只是讲了一个开头还没有讲完,今天我们继续。

像原来我们写m++你得加锁,在多线程访问的情况下,那现在我们可以用AtomicInteger了,它内部就已经帮我们实现了原子操作,直接写 count.incrementAndGet(); //count1++ 这个就相当于count++。原来我们对count是需要加锁的,现在就不需要加锁了。

我们看下面小程序,模拟,我们计一个数,所有的线程都要共同访问这个数count值,大家知道如果所有线程都要访问这个数的时候,如果每个线程给它往上加了10000,你这个时候是需要加锁的,不加锁会出问题。但是,你把它改成AtomicInteger之后就不用在做加锁的操作了,因为incrementAndGet内部用了cas操作,直接无锁的操作往上递增,有同学可能会讲为什么要用无锁操作啊,原因是无锁的操作效率会更高。

第四节:LockSupport、淘宝面试题与源码阅读方法论

首先我们简单回顾一下前面三节课讲的内容,分别有线程的基本概念、synchronized、volatile、AtomicXXX、各种JUC同步框架(ReentrantLock、CountDownLatch、CyclicBarrier、Phaser、ReadWriteLock-StampedLock、Semaphore、Exchanger、LockSupport),其中synchornized重点讲了一下,包括有synchornized的底层实现原理、锁升级的概念(四种状态:无锁、偏向锁、轻量级锁、重量级锁),volatile我们讲了可见性和禁止指令重排序如何实现。

synchronized和ReentrantLock的不同?

synchronized:系统自带、系统自动加锁,自动解锁、不可以出现多个不同的等待队列、默认进行四种锁状态的升级

ReentrantLock:需要手动枷锁,手动解锁、可以出现多个不同的等待队列、CIS的实现本章我们补一个小漏洞,它叫LockSupport,然后我们分析两道面试题,紧接着我会教大家阅读源码的技巧,源码层出不穷,生生不息,掌握了源码的阅读技巧,大家培养出了阅读源码兴趣的时候,之后好多代码,你需要自己去抠,抠出来才是你自己的,最后我们会分析AQS源码,以上是我们本章主讲的内容概述。

第五节:AQS源码阅读与强软弱虚4种引用以及ThreadLocal原理与源码

今天咱们继续讲AQS的源码,在上节课我教大家怎么阅读AQS源码,跑不起来的不读、解决问题就好 —目的性、一条线索到底、无关细节略过,读源码的时候应该先读骨架,比如拿AQS来说,你需要了解AQS是这么一个数据 结构,你读源码的时候读起来就会好很多,在这里需要插一句,从第一章到本章,章章的内容都是环环相扣的,没学习前边,建议先去补习一下前面的章节。

第六节:并发容器

今天是第六天了,这节课本来想上一个大而全的课,后来发现这个实在目标太大了,大而全的概念就是上节课讲到的那张容器图中的每一个都讲的非常的细致,然后去谈他们的源码。但是如果这么讲的话我们高并发的课就讲不完了,所以也别着急,后面单独开一门课来讲集合,集合的发展历程,现在为什么讲这个并发容器呢,主要是为了线程池做准备,线程池里有一个参数就是用并发容器来做你工作任务的容器。

 

第七节:线程池

今天这节课呢,我们通过一道面试把前面讲的哪些基础复习一下,然后再开始线程池这部分的内容,我们一点一点来看。

这道面试题呢实际上是华为的一道面试题,其实它里面是一道填空题,后来就很多的开始考这道题,这个面试题是两个线程,第一个线程是从1到26,第二个线程是从A到一直到Z,然后要让这两个线程做到同时运行,交替输出,顺序打印。那么这道题目的解法有非常多。

第八节:线程池与源码阅读
第九节:JMH与Disruptor

今天我们讲两个内容,第一个是JMH,第二个是Disruptor。这两个内容是给大家做更进一步的这种多线程和高并发的一些专业上的处理。生产环境之中我们很可能不自己定义消息队列,而是使用Disruptor。我们生产环境做测试的时候也不是像我说的那样写一个start写一个end就测试完了。在这里给大家先介绍专业的JMH测试工具,再给大家介绍Disruptor号称最快的消息队列。

 

 

需要这本武功秘籍的来修炼自己内功的小伙伴,可以转发此文关注小编↓↓↓

希望能够让大家在面对面试官的"面试连珠炮"和“刨根问底”之下,对答如流,拿到30-50W的年薪!~~