• 互联网大厂高频重点面试题 (第2季)JUC多线程及高并发


    本期内容包括

    JUC多线程并发、JVM和GC等目前大厂笔试中会考、面试中会问、工作中会用的高频难点知识。
    斩offer、拿高薪、跳槽神器,对标阿里P6的《尚硅谷_互联网大厂高频重点面试题(第2季)》发布。本套课程总结分析了2019年大厂互联网公司常见常考的技术点,通过对40多个题目共计120集视频详细全面的讲解,让大家深刻掌握、扎实吃透当前的主流Java高级技术。
    在这里插入图片描述
    在这里插入图片描述

    在这里插入图片描述
    在这里插入图片描述

    在这里插入图片描述

    在这里插入图片描述

    NoSQL数据库Redis
    在这里插入图片描述
    在这里插入图片描述

    消息中间件MQ
    在这里插入图片描述

    在这里插入图片描述
    在这里插入图片描述

    在这里插入图片描述
    在这里插入图片描述

    JUC多线程及高并发
    在这里插入图片描述
    并发和并行有什么区别
    并发:多个线程去访问同一个资源
    并行:各种事情同时去做,一边干什么,一边干什么
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述

    在这里插入图片描述

    请谈谈你对volatile的理解

    volatile是什么

    在这里插入图片描述
    三大特性
    在这里插入图片描述

    JMM内存模型之可见性

    JMM:java内存模型
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    各个线程对主内存中的数据进行改变,不是直接修改,而是会把age=25拷贝到自己的工作内存中再进行改变
    t1改为37后要把新数据写回到主内存中,t2,t3不知道主内存中的值已经改变了
    所以我们需要有一个机制:JMM内存模型的可见性,只要有一个线程改变数据后要写回到主内存中,其它的线程马上就会知道主内存中的数据已经改变了

    可见性的代码验证说明

    在这里插入图片描述

    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    3秒之后,a线程已经把number改了,但是main线程不知道,对main线程不可见,还在傻傻的等着,没有人通知我

    现在修改程序,加了volatile
    在这里插入图片描述
    增加了内存之间的可见性
    在这里插入图片描述

    在这里插入图片描述

    volatile不保证原子性

    原子性:不可分割、完整性,也就是某个线程正在做某个具体业务时,中间不可以被加塞或者被分割,需要整体完整,要么同时成功,要么同时失败。
    在这里插入图片描述
    把验证可见性的代码写到一个方法seeokbyvolatile

    20个线程去调用addplus方法,每个线程调用1000次,则结果应该是2000。
    多线程编程的模板forthread10是自己设置的快捷键

    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述

    volatile不保证原子性理论解释

    在这里插入图片描述

    在这里插入图片描述
    在这里插入图片描述
    轻量级就是乞丐版的sunchronized
    不要杀鸡焉用牛刀,太重了

    拷贝回自己的内存空间,每个人都拿到0,写回到主内存时,线程1写回到的时候被挂起了,线程2歘的写回了。然后线程1恢复后又写回了一遍,把原来的1给覆盖了。
    在这里插入图片描述

    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    三个线程都拿到1,都在各自的工作内存中加1,写回到的时候,没有拿到最新的值就又写了,写覆盖

    volatile不保证原子性问题解决

    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述

    volatile指令重排案例1

    在这里插入图片描述
    在这里插入图片描述
    不可以,必须考虑指令之间的数据依赖性
    在这里插入图片描述
    加了volatile之后是禁止指令重排

    volatile指令重排案例2

    在这里插入图片描述
    答案是6

    但是指令重排后,答案可能是5

    所以在这些变量前面加上volitaile就可以禁止指令重排

    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述

    单例模式在多线程环境下可能存在安全问题

    在这里插入图片描述
    单例模式有六种
    掌握一种即可
    第一步 定义私有的实例变量
    第二步 构造方法
    第三步 新建,返回同一个变量
    在这里插入图片描述
    比较引用类型,内存地址
    在这里插入图片描述

    在这里插入图片描述
    在多线程坏境下,单例模式出现了问题
    在这里插入图片描述
    如果加上synchronized,在多线程的环境控制住了
    但是太重了,并发性下降了

    单例模式volatile分析

    DCL模式 Double Check Lock双端检锁机制

    在加锁之前和之后都进行一次检测
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    地址不为空,但是内容为空
    所以要在instance变量上面加上volatile
    在这里插入图片描述
    总结:
    在这里插入图片描述

    CAS你知道吗?

    在这里插入图片描述

    CAS是什么

    CAS compare and set 比较并交换
    在这里插入图片描述
    多个线程去操作主内存中的数据。
    一个叫做期望值、一个叫做更新值

    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    主内存中数据是5
    一个线程拷贝回去自己的工作内存,对它进行修改,然后写回到主内存的时候,会进行比较和交换,如果和拷贝的数据一样的话,就将改变后的数据写回去;否则的话,就不进行写回。
    在这里插入图片描述

    CAS底层原理上

    在这里插入图片描述
    当前对象 内存偏移量

    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述

    AtomicInteger 的getandincrement方法底层其实是CAS思想+套的是unsafe类的CPU原语来保证原子性,
    底层思想是比较并交换,真实值和期望值相等就交换成功,否则就失败,失败就再来,直到比较成功为止。

    CAS底层原理下

    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述

    在这里插入图片描述

    在这里插入图片描述

    CAS缺点

    CAS能够不加锁保证一致性,并发性加强了
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述

    原子类AtomicInteger的ABA问题谈谈?原子更新引用知道吗?

    在这里插入图片描述

    ABA问题

    在这里插入图片描述

    在这里插入图片描述
    2号线程比1号线程快,把原来的A改为B,又改为A。
    1号线程回来后,期望的和原来的一样,以为没有改变过,于是写回主内存。
    但是中间有猫腻,2号线程已经把它改过了又改回去了。

    在这里插入图片描述

    AtomicReference原子引用

    在这里插入图片描述
    只管开头和结尾,没有管中间。
    在这里插入图片描述
    原子引用的泛型类

    原子User类型
    在这里插入图片描述
    在这里插入图片描述

    在这里插入图片描述

    AtomicStampedReference版本号原子引用

    时间戳原子引用
    在这里插入图片描述
    在这里插入图片描述

    ABA问题的解决

    在这里插入图片描述
    在这里插入图片描述
    修改成功,

    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述

    我们知道ArrayList是线程不安全的,请编码写一个不安全的案例并给出解决方案。

    集合类不安全之并发修改异常

    ArrayList底层是一个数组
    什么类型的数组?
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    数组初始长度为10,超过10以后进行扩容。

    它是线程不安全的。
    举一个线程不安全的案例。
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述

    把3改为30
    在这里插入图片描述

    java.util.ConcurrentModificationException
    并发修改异常

    线程不安全是指:在多线程的情况下,
    方法一:
    在这里插入图片描述
    Vector类可以解决这个问题,加锁一致性可以保证,但是并发性急剧下降。

    不许用Vector
    方法二:
    在这里插入图片描述

    Map和Set也是不安全的集合类
    在这里插入图片描述
    方法三:

    集合类不安全之写时复制

    在这里插入图片描述
    在这里插入图片描述
    写时复制
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述

    锁、扩容、写新元素
    在这里插入图片描述
    在这里插入图片描述

    集合类不安全之Set

    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述

    集合类不安全之Map

    在这里插入图片描述
    在这里插入图片描述

    TransferValue醒脑小练习

    在这里插入图片描述
    在这里插入图片描述
    传值还是传引用
    在这里插入图片描述
    在这里插入图片描述
    age属于main方法的,然后调用方法时复印了一份传给它,然后方法把复印件给改动了
    在这里插入图片描述
    我只是给你复印了一份值,原件根本没动,所以第一个age还是20

    person是main的,传引用传内存地址给方法,两个引用指向了同一个地址,这时把这个地址的值改动了
    在这里插入图片描述

    str是属于main方法的,这个池子里有了abc
    这个池子里面没有xxx,那么就重新创建一个指向它
    在这里插入图片描述
    在这里插入图片描述

    公平锁/非公平锁/可重入锁/递归锁/自旋锁 谈谈你的理解?请手写一个自旋锁。

    在这里插入图片描述

    Java锁之公平锁/非公平锁

    在这里插入图片描述

    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    无参数:不公平 允许某个同学突然出来加塞
    有参数:公平 队列先来后到
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    synchronized等同于锁,非公平锁
    被它抢到了锁上了

    Java锁之可重入锁和递归锁理论

    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述

    Java锁之可重入锁和递归锁代码验证

    在这里插入图片描述
    资源类

    线程操作资源类
    在这里插入图片描述
    在这里插入图片描述
    t1线程在外层方法获取锁的时候,t1在进入内层方法会自动获取锁
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    只要锁匹配,几把锁都可以。
    在这里插入图片描述
    在这里插入图片描述

    Java锁之自旋锁理论知识

    在这里插入图片描述

    Unsafe类+CAS思想(自旋锁)
    在这里插入图片描述

    Java锁之自旋锁代码验证

    在这里插入图片描述
    在这里插入图片描述
    如果是第一次进来线程,就不进循环
    在这里插入图片描述
    A线程进来,发现期望的是空的,那么while的条件就是false,于是不进入循环,直接拿到了锁。
    B线程进来,发现期望的值不是空,那么while的条件就是true,于是它进入锁中,一直会循环的判断,直到期望的值是空了,才能推出循环,获得锁。
    在这里插入图片描述
    在这里插入图片描述
    BB等5秒钟,等A解锁了,B才能解锁

    Java锁之读写锁理论知识

    在这里插入图片描述
    在这里插入图片描述

    Java锁之读写锁代码验证

    在这里插入图片描述
    以前使用锁和synchronized读和写通通不能并发执行,数据一致量可以保证,但并发性急剧下降。

    线程操作资源类
    高内聚低耦合
    在这里插入图片描述
    在这里插入图片描述

    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    锁不能进行细粒度的划分,只能把全部进行封杀
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述

    CountDownLatch/CyclicBarrier/Semaphore使用过吗?

    在这里插入图片描述

    CountDownLatch

    在这里插入图片描述
    火箭发射
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述

    在这里插入图片描述
    使用枚举
    在这里插入图片描述

    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述

    CyclicBarrier Demo

    循环屏障
    人都到齐了才能开会
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    一个是减法,倒计时
    一个是加法,累积

    Semaphore Demo

    多个线程强多个资源
    信号灯
    资源为1时就退化成synchronized
    在这里插入图片描述
    在这里插入图片描述
    不写是非公平锁,效率高允许加塞
    可以复用
    可以抢占可以释放
    在这里插入图片描述
    在这里插入图片描述
    停3秒钟
    在这里插入图片描述

    阻塞队列知道吗?

    在这里插入图片描述

    阻塞队列理论

    在这里插入图片描述

    阻塞队列接口结构和实现类

    生产者 消费者 sychronized wait notify
    在这里插入图片描述
    队列:先进先出
    阻塞:
    在这里插入图片描述
    在这里插入图片描述
    生产者消费者模式:用阻塞对垒写

    在这里插入图片描述

    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述

    在这里插入图片描述

    阻塞队列API之抛出异常组

    在这里插入图片描述

    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    检查队列的首元素是谁?
    a
    先进先出

    阻塞队列API之返回布尔值组

    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述

    在这里插入图片描述

    在这里插入图片描述
    队列的首元素是谁
    在这里插入图片描述
    在这里插入图片描述

    阻塞队列API之阻塞和超时控制

    在这里插入图片描述
    在这里插入图片描述

    阻塞的意思是:我现在满了,就等着,直到有元素出去。因为我不能丢消息呀,就等着
    在这里插入图片描述
    在这里插入图片描述
    取不出来就堵着

    过时不候
    超时
    在这里插入图片描述
    在这里插入图片描述
    这时候没有等2秒钟
    在这里插入图片描述
    只阻塞2秒钟。2秒钟之后就打印出false

    阻塞队列之同步SynchronizedQueue队列

    在这里插入图片描述
    在这里插入图片描述
    0库存,生产出来的马上被别人拿走
    在这里插入图片描述
    你不消费,你想到里面插第二个你插不进去
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述

    线程通信之生产者消费者传统版

    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述

    在这里插入图片描述

    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述

    防止虚假唤醒
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    没有控制住,生产了2个
    所以唤醒的时候要加入循环
    在这里插入图片描述

    synchronized和lock有什么区别

    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述

    锁绑定多个条件condition

    在这里插入图片描述
    在这里插入图片描述

    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述

    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述

    线程通信之生产者消费者阻塞队列版

    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述

    线程池用过吗?ThreadPoolExecutor谈谈你的理解?

    在这里插入图片描述

    Callable接口

    在这里插入图片描述
    在这里插入图片描述
    区别:
    runnable接口没有返回值,不会抛异常,实现run
    callable接口有返回值,会抛异常,实现call
    在这里插入图片描述
    要的是runnable,有的是callable,如何把它们之间加上关系

    生活的例子:两个同学,我默认接收的参数是张,但是,要找一个中间人
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    FutureTask实现穿针引线的作用。

    在这里插入图片描述
    在这里插入图片描述
    已经有runnable接口,为什么还需要callable接口呢?
    在这里插入图片描述
    多个线程都要使用cllable,每次都要返回一个成功或者失败的返回值。
    适配模式。
    在这里插入图片描述
    在这里插入图片描述

    get()建议放在最后
    在这里插入图片描述
    因为我们不会等这个线程,给它充足的时间去计算
    在这里插入图片描述
    在这里插入图片描述
    如果把get放到前面,mian线程就被堵住了
    在这里插入图片描述
    所以这里可以加一个循环的判断!等算完了,才往下做

    在这里插入图片描述
    两个线程都开始做同一个任务,只会执行一次!即复用
    在这里插入图片描述
    如果说非要进去!那么就要启动多个futuretask

    线程池使用及优势

    在这里插入图片描述
    永远传参数传接口

    在这里插入图片描述
    在这里插入图片描述
    看CPU的核数

    在这里插入图片描述

    线程池3个常用使用方式

    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    ThreadPoolExecutor
    辅助工具类
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    一池固定线程、一池一线程、一池多线程
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述

    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述

    线程池7大参数入门简介

    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述

    线程池7大参数深入介绍

    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述

    线程池底层工作原理

    在这里插入图片描述
    在这里插入图片描述

    线程池用过吗?生产上你如何设置合理参数。

    在这里插入图片描述

    线程池的4种拒绝策略理论简介

    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    从而降低任务流量。

    线程池实际中使用哪一个

    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    无界的阻塞队列
    在这里插入图片描述

    线程池的手写改造和拒绝策略

    在这里插入图片描述
    在这里插入图片描述
    最高几个客户来办业务,就报拒绝了
    在这里插入图片描述
    在这里插入图片描述
    默认的拒绝策略:马上报异常
    在这里插入图片描述
    调用者运行机制:不会抛弃任务也不会抛出异常,而是将某些任务回退到调用者,从而降低新任务的流量
    谁让你调用我的,那么你就去找他
    在这里插入图片描述

    抛弃队列中等待时间最久的任务
    在这里插入图片描述
    这样的话只能完成8个人的业务,剩下的就直接丢弃了

    线程池配置合理线程数

    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述

    死锁编码及定位分析

    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述

    单线程不可能有死锁!没人跟你抢,你怎么会死锁。

    两把锁

    持有自己的锁还妄图得到别人的锁。
    在这里插入图片描述
    在这里插入图片描述

    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述

    在这里插入图片描述
    在这里插入图片描述

  • 相关阅读:
    Django学习路10_创建一个新的数据库,指定列名并修改表名
    设计模式_单例模式的懒汉式实例化
    设计模式_理解单例设计模式
    Django学习路9_流程复习
    Django学习路8_学生表和班级表级联并相互查询信息
    Django学习路7_注册app到能够在页面上显示app网页内容
    es6基础:类、继承、重写
    简单的下拉刷新
    callback&&callback()
    转 五大浏览器四大内核
  • 原文地址:https://www.cnblogs.com/cxhfuujust/p/11720264.html
Copyright © 2020-2023  润新知