目录
-
锁升级
最开始就是偏向锁,一个线程进入到同步代码块的时候会将,会将对象的头部写上该线程的偏向锁,加上偏向锁之后同一个线程再次进入同步代码块的时候就不用重复申请锁和释放锁,这样能够减少性能的开销,直到其他线程申请锁的时候,会尝试获取锁,将对象头部的锁信息改为偏向该线程,对象头的锁信息切换达到20次阈值的时候升级为轻量级锁。
轻量级锁,当多个线程进行锁竞争的时候会采用CAS尝试获取锁,竞争不到的线程此时不会阻塞在队列上,而是会自旋等待,线程会空循环一段时间,这样的好处就是不用频繁的线程切换减少了性能开销。但是当自旋超过一定时间就会升级为重量级锁。
重量级锁,重量级锁会让没有竞争到锁的线程进入到阻塞队列中,直到申请到锁的线程将锁资源释放掉才能继续竞争,这样做性能开销相对较大
-
volatile
volatile能够保证线程对资源修改的可见性,当一个线程对资源修改的时候,此次修改会写回主内存并无效化其他线程的本地缓存,会重新读取一遍主内存中最新值
-
cas
CAS是一种乐观锁的实现形式。CAS操作是一个线程想要做出修改的时候,会先做出修改,再去跟预期值进行对比,如果与预期值一致则会写回到内存当中,如果不一致则证明被其他线程所修改然后重新进行CAS操作。
-
线程池
线程池的七大参数——线程工厂、核心线程数、等待队列、最大线程数、空闲等待时间、时间单位、拒绝策略
通过线程池能够避免频繁的创建和销毁线程,能够减少线程创建和上下文切换带来的开销,能够更高效的管理系统资源和提供并发处理能力
-
死锁
两个或多个线程相互持有对方所需要的资源,并互相等待,这样就造成了死锁
死锁的四个必要条件:资源互斥、不可剥夺、循环等待、请求和保持条件
-
进程间通信
可以采用管道、共享内存、信号量、消息队列、套接字(socket)来进行通信
-
线程、进程、协程
进程是操作系统分配资源的基本单位,一个进程至少包含一个线程
线程是进程中的一个执行单元,是操作系统调度的最小执行单位
协程是一种用户级线程,由程序员控制切换,可以实现非抢占式的多任务处理(查的)
-
jmm
所有变量都存在主存中,主存是线程共享区域;每个线程都有自己独立的工作内存,是一个线程独享的区域,线程想要操作变量就必须从主存中copy变量到自己的工作区,每个线程的工作区都是互相隔离的。
-
aqs
抽象队列同步器,java并发编程中的一个抽象类,提供了锁和同步器的框架。ReentrantLock、CountDownLaunch、Semaphore等
-
可重入锁
线程在持有锁的情况下,再一次获取同一个锁不会发生死锁,适用于在递归函数获取同一个锁
-
countdownlatch
给计数器设置一个初始值,当调用CountDown()时计数器减一,当调用await() 时判断计数器是否归0,不为0就阻塞,直到计数器为0。(等待多个子线程完成某个任务,然后再继续执行主线程的下一步操作)
-
同步和异步
同步是任务按照顺序依次执行,前一个任务完成后才能下一个任务
异步是任务执行相互独立,不需要等待其他任务完成才能继续执行
-
如果让你设计垃圾收集策略 你会如何设计
标记清除:标记不需要回收的对象(引用计数、可达性分析),然后清除掉未标记的
标记整理:标记后将存活的对象向一方统一移动,然后清除边界外的垃圾对象(老年代的垃圾回收)
复制算法:内存分为两块,只使用一块,需要回收的时候将存活的对象放入另一个区域,然后清空之前的区域(新生代的From和to)
-
如果让你设计类加载机制 你会怎样设计
类加载器负责从文件系统、网络或其他来源加载类的字节码,并将其转换为JVM可以理解的格式。JVM支持多个类加载器,每个加载器都负责加载特定类型的类。
从父加载器到子类加载器分别为:
BootStrapClassLoader(启动类加载器) 加载路径——JAVA_HOME/jre/lib
ExtensionClassLoader(扩展类加载器) 加载路径——JAVA_HOME/jre/lib/ext
ApplicationClassLoader (应用程序类加载器) 加载路径——classPath
双亲委派,会依次向上交给父类加载器,直到顶层的启动类加载器,只有父类无法加载的时候子类才会加载
-
缓存击穿 和 缓存雪崩
缓存击穿是查询或操作一条缓存中没有的数据的时候,会将请求直接打到数据库中,当恶意发出很多数据库中没有的请求时,会对内存造成很大的影响,可以用布隆过滤器来解决,它会快速判断是否存在这条数据。
缓存雪崩是指有大量缓存都在短时间内过期的时候,会有大量的请求都直接请求到数据库当中,造成巨大的压力,可以针对缓存数据设置不同的过期时间或设置热点数据永不过期来解决缓存雪崩的问题,也可以配置多点Redis集群,可以在一个节点出现问题时分配任务到其他节点
-
redis在你项目中是怎么用的
将经常查询的数据放入Redis中做缓存,减少后端数据库的压力。
分布式锁:分布式系统中用作确保数据的一致性和并发控制,采用Redis的原子操作和特性实现分布式锁,避免多个线程同时修改
-
mq在你项目中怎么用的
实现发布/订阅模式,消息发布者将消息发布到特定的topic,订阅者可以订阅需要的主题来接收消息
实现点对点模式,消息发布者将消息发送到一个队列,接收者从队列里接收消息
-
你怎么防止消息重复消费和消息丢失问题
使用唯一消息ID来进行消息的去重判断
消息确认机制,消费者成功处理消息之后才会向消息队列发送确认信息
幂等性处理让多次执行操作产生的结果与执行一次的相同(Redis)
-
rpc接触过吗,讲讲你对rpc的认识
远程过程调用,是能够实现分布式系统中不同计算机通信的协议。可以将分布式系统的不同模块连接起来,使其能够互相通信和合作。通过定义接口和方法,客户端可以直接调用服务器的函数,而无需关心底层的网络实现细节
-
序列化和反序列化是怎么处理的,你了解多少
序列化是将对象转换为字节流的过程,反序列化则是将字节流转换回对象的过程
实现Serializable接口,使用ObjectOutputStream来进行序列化(通过创建对象并调用其writeObject方法将对象转为字节流)
使用ObjectInputStream来进行反序列化(通过创建对象并调用其readObject方法将字节流转为对象)