版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
Java线程安全高频面试题及详细答案(实战版)1.什么是线程安全?线程不安全的根本原因是什么?参考答案:线程安全简单来说,就是多线程同时操作共享资源时,程序不会出现数据错乱、结果异常等问题,最终执行结果和单线程串行执行的结果一致。线程不安全的根本原因主要有三点:第一,共享可变资源。多个线程同时访问、修改同一个变量、对象、集合等共享数据,这是前提条件,如果没有共享数据,就不存在线程安全问题。第二,CPU原子性破坏。很多看似简单的操作不是原子操作,比如i++,本质是读取、运算、赋值三步操作,多线程下三步操作会互相穿插覆盖,导致数据丢失。第三,Java内存模型的可见性、有序性问题。线程会把共享变量缓存到本地内存,一个线程修改后,其他线程感知不到(可见性问题);编译器和CPU会对指令重排序,导致代码执行顺序和编写顺序不一致(有序性问题),最终引发业务异常。2.什么是原子性、可见性、有序性?分别怎么保证?参考答案:原子性指一个或多个操作要么全部执行成功,要么全部不执行,执行过程中不会被其他线程打断。保证方式:synchronized锁、Lock显式锁、JUC原子类(AtomicInteger等)。可见性指一个线程修改了共享变量的值,其他线程能够立刻感知到最新值,而不是读取本地缓存的旧值。保证方式:volatile关键字、synchronized、Lock锁(锁的释放会强制刷新主内存)。有序性指代码的执行顺序和代码编写的逻辑顺序一致,避免指令重排序导致的逻辑错乱。保证方式:volatile关键字(禁止指令重排)、synchronized、Lock锁、happens-before规则。3.volatile关键字的作用是什么?能不能保证线程安全?参考答案:volatile核心有两个作用:一是保证共享变量的可见性,变量修改后立即刷新到主内存,其他线程读取时直接从主内存加载最新值;二是禁止指令重排序,避免多线程下因指令顺序错乱导致的BUG。volatile不能保证线程安全,核心原因是它不保证原子性。比如常见的计数场景i++,volatile只能保证每次读取的i是最新值,但无法保证读取、自增、赋值三步操作不被打断。多个线程同时读取同一个值,分别自增后赋值,就会出现计数少加的问题。所以volatile适合状态标记、只读变量这类单读单写场景,不适合复合运算场景。4.synchronized关键字的原理、用法、锁升级机制?参考答案:基本原理synchronized是Java内置的悲观锁,底层依赖JVM实现,通过对象头的MarkWord存储锁状态,保证同一时间只有一个线程能获取锁、执行同步代码,保证原子性、可见性、有序性。三种用法1.修饰实例方法:锁的是当前对象this,不同对象之间互不影响;2.修饰静态方法:锁的是当前类的Class对象,所有实例对象共用一把锁;3.修饰代码块:锁的是指定的对象,粒度最细,性能最好。锁升级机制(JDK1.6之后优化)为了提升synchronized性能,JVM引入锁升级,锁状态只能单向升级,不能降级:1.无锁:初始状态,没有线程竞争;2.偏向锁:单线程频繁获取锁,JVM偏向该线程,无需每次加锁解锁,效率极高;3.轻量级锁:出现少量线程竞争,线程通过CAS自旋尝试获取锁,不阻塞;4.重量级锁:竞争激烈,CAS自旋失败,线程阻塞,进入操作系统内核态,性能下降。5.synchronized和ReentrantLock的区别?参考答案:两者都是可重入锁,保证线程安全,但区别非常明显,面试核心对比点如下:1.底层实现不同:synchronized是JVM内置锁,底层由操作系统实现;ReentrantLock是JDK层面的显式锁,基于AQS(抽象队列同步器)实现,纯Java代码实现。2.加锁解锁方式不同:synchronized隐式加锁解锁,代码执行完自动释放锁;ReentrantLock需要手动lock()、unlock(),必须在finally中解锁,避免死锁。3.功能扩展性不同:ReentrantLock功能更强,支持公平锁/非公平锁切换、可中断锁、超时锁、条件变量Condition精准唤醒;synchronized只能是非公平锁,不支持中断和超时。4.性能不同:JDK1.6之后synchronized做了锁升级优化,性能基本和ReentrantLock持平,低竞争场景下甚至更优;高竞争场景ReentrantLock可控性更好。5.锁粒度灵活性:ReentrantLock粒度更灵活,适合复杂并发场景;synchronized使用更简单,适合常规同步场景。6.什么是可重入锁?为什么需要可重入?参考答案:可重入锁指同一个线程获取到锁之后,在持有锁的期间,可以再次重复获取同一把锁,不会出现自己阻塞自己的情况。synchronized和ReentrantLock都是可重入锁。需要可重入的核心目的是避免死锁、简化代码层级。比如一个同步方法A内部调用了另一个同步方法B,如果锁不可重入,线程已经持有A的锁,执行B时会再次尝试获取锁,最终自己阻塞自己,形成死锁。可重入锁通过记录锁持有次数,每次重入次数+1,解锁次数-1,次数为0才释放锁,完美解决这个问题。7.什么是死锁?产生死锁的四个必要条件?如何避免死锁?参考答案:死锁是多个线程互相持有对方需要的锁,同时互相等待对方释放锁,所有线程永久阻塞,程序卡死无法继续执行。死锁四大必要条件(必须同时满足)1.互斥条件:锁资源同一时间只能被一个线程持有;2.请求与保持:线程持有一把锁,同时请求获取另一把被占用的锁,不释放已有锁;3.不可剥夺:锁只能被持有者主动释放,其他线程不能强行抢占;4.循环等待:多个线程之间形成锁资源的循环等待链路。避免死锁的方案核心思路是破坏四大必要条件中的任意一个:1.统一锁获取顺序:所有线程获取多把锁时,严格按照固定顺序获取,破坏循环等待;2.超时锁机制:使用ReentrantLock的tryLock(timeout),获取锁超时则放弃,避免永久等待;3.减少锁嵌套:尽量避免在锁内部再获取其他锁;4.主动释放无用锁:持有锁期间,如果不需要当前锁资源,主动释放,破坏请求与保持条件。8.普通集合为什么线程不安全?ConcurrentHashMap如何保证线程安全?参考答案:ArrayList、HashMap线程不安全原因1.没有加任何同步锁,多线程并发读写时,put、add等复合操作会出现覆盖、数据丢失;2.HashMap并发扩容时,JDK1.7会出现链表环形死循环、数据丢失,JDK1.8解决了环形链表问题,但仍会数据覆盖;3.迭代遍历期间,其他线程修改集合,会触发并发修改异常ConcurrentModificationException。ConcurrentHashMap线程安全原理(JDK1.8)1.CAS+synchronized实现细粒度锁:插入元素时,无冲突用CAS赋值,出现线程冲突时,对当前数组桶的头节点加synchronized锁,只锁住单个桶,不影响其他桶操作,并发效率极高;2.取消分段锁:摒弃JDK1.7的Segment分段锁,锁粒度进一步细化;3.扩容并发协助:支持多线程协助扩容,提升扩容效率;4.读写分离:读操作无锁,基于volatile保证可见性,写操作加细粒度锁,兼顾安全和性能。9.什么是ABA问题?如何解决?参考答案:ABA问题是CAS操作的经典并发问题。CAS的核心逻辑是比较当前值和预期值,一致则更新。简单场景:线程1读取变量值为A,此时线程2抢占CPU,将值改成B,又改回A。线程1再次比较,发现还是A,认为变量没有被修改,正常执行更新操作,但实际上变量已经被改动过,可能引发数据异常。解决方案:核心是增加版本号标记,不单纯比较变量值,同时比较版本号。每次修改变量,版本号自增,即使值变回原来的数值,版本号也会变化,CAS可以精准判断数据是否被修改。JDK提供的AtomicStampedReference就是基于版本号解决ABA问题,适合需要规避ABA的业务场景。10.线程池如何保证线程安全?核心参数和拒绝策略?参考答案:线程安全保障线程池内部通过AQS机制、阻塞队列、线程状态变量(volatile修饰)保证并发安全。任务提交、队列存取、线程状态修改都通过CAS和锁控制,多线程提交任务不会出现队列数据错乱、线程状态混乱的问题。核心参数1.corePoolSize:核心线程数,线程池常驻线程;2.maximumPoolSize:最大线程数,任务堆积时扩容的上限;3.keepAliveTime:非核心线程空闲超时时间,超时回收;4.workQueue:任务阻塞队列,存储等待执行的任务;5.threadFactory:线程工厂,创建线程;6.handler:任务拒绝策略。四种拒绝策略1.AbortPolicy(默认):直接抛出异常,阻止任务提交;2.CallerRunsPolicy:由提交任务的主线程自己执行任务;3.DiscardPolicy:直接丢弃当前新任务,不报错;4.DiscardOldestPolicy:丢弃队列中最旧的未执行任务,添加新任务。11.乐观锁和悲观锁的区别?各自适用场景?参考答案:悲观锁默认并发竞争一定存在,每次操作数据都先加锁,独占资源,其他线程阻塞等待。典型实现:synchronized、ReentrantLock。适用场景:高并发写场景、竞争激烈,写操作频繁,冲突概率高,加锁可以避免大量CAS重试消耗。乐观锁默认并发没有冲突,不加锁,直接操作数据,更新时通过版本号、CAS校验判断是否冲突,冲突则重试或放弃。典型实现:CAS、Atomic原子类、数据库版本号锁。适用场景:读多写少、竞争不激烈,无锁开销小,执行效率高,少量冲突重试即可。12.日常开发中保证线程安全的常用方案有哪些?参考答案:结合业务场景,从最优到兜底排序,常用方案有:1.无共享设计:尽量避免共享可变变量,多用局部变量、ThreadLocal,从根源杜绝线程安全问题,这是最优方案;2.使用并发安全容器:用ConcurrentHashMap、CopyOnWriteArrayList等JUC并发集
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 2025下半年幼儿园教资《保教知识与能力》真题及答案解析
- 氢气质量流量控制器和流量计:氢能基础设施加速商业化促进设备进入价值升级周期
- 2026年4月自考试题及答案
- 2026年《新型抗肿瘤药物临床应用指导原则》培训试题(附答案)
- 2026年职业暴露预防及处理培训试题及答案
- 皮肤科疾病诊断辅助
- 数字疗法的患者数据安全策略
- 高中物理教资面试动量守恒答案
- 他汀类药物治疗慢性心力衰竭的利弊探讨
- 安全生产总结新闻稿讲解
- 《德州扒鸡》课件
- 报名表的模板
- 单位资产清查报告范文(12篇)
- 道路运输和其他安全安全生产实务注册安全工程师考试(初级)试卷与参考答案(2024年)
- 《新媒体对公共管理的影响研究》11000字(论文)
- GB/T 44570-2024塑料制品聚碳酸酯板材
- TCSBZ 004-2024 石材护理技术规范
- CHZ 3002-2010 无人机航摄系统技术要求(正式版)
- 国中康健集团限公司2022年第二批高校毕业生招聘上岸笔试历年难、易错点考题附带参考答案与详解
- 说课课件《观察鸡卵的结构》
- 第六章公共预算:决策及其经济
评论
0/150
提交评论