互联网大厂高频重点面试题 (第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个人的业务,剩下的就直接丢弃了

线程池配置合理线程数

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

死锁编码及定位分析

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

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

两把锁

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

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

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

posted on 2019-10-22 15:52  cxhfuujust  阅读(2816)  评论(0编辑  收藏  举报

导航