- 1、原创力文档(book118)网站文档一经付费(服务费),不意味着购买了该文档的版权,仅供个人/单位学习、研究之用,不得用于商业用途,未经授权,严禁复制、发行、汇编、翻译或者网络传播等,侵权必究。。
- 2、本站所有内容均由合作方或网友上传,本站不对文档的完整性、权威性及其观点立场正确性做任何保证或承诺!文档内容仅供研究参考,付费前请自行鉴别。如您付费,意味着您自己接受本站规则且自行承担风险,本站不退款、不进行额外附加服务;查看《如何避免下载的几个坑》。如果您已付费下载过本站文档,您可以点击 这里二次下载。
- 3、如文档侵犯商业秘密、侵犯著作权、侵犯人身权等,请点击“版权申诉”(推荐),也可以打举报电话:400-050-0827(电话支持时间:9:00-18:30)。
- 4、该文档为VIP文档,如果想要下载,成为VIP会员后,下载免费。
- 5、成为VIP后,下载本文档将扣除1次下载权益。下载后,不支持退款、换文档。如有疑问请联系我们。
- 6、成为VIP后,您将拥有八大权益,权益包括:VIP文档下载权益、阅读免打扰、文档格式转换、高级专利检索、专属身份标志、高级客服、多端互通、版权登记。
- 7、VIP文档为合作方或网友上传,每下载1次, 网站将根据用户上传文档的质量评分、类型等,对文档贡献者给予高额补贴、流量扶持。如果你也想贡献VIP文档。上传文档
JVM内存模型高频面试题及答案
一、基础概念题
问题:JVM内存模型(JMM)的核心目标是什么?和JVM内存结构有什么区别?
答案:JMM的核心目标是解决多线程并发时,共享变量的可见性、原子性、有序性问题,定义线程和主内存之间的交互规则。而JVM内存结构是物理划分(如堆、栈、方法区),关注“内存放什么”;JMM是逻辑模型,关注“多线程如何安全访问内存”——比如堆是JVM内存结构的一部分,而JMM规定了多个线程操作堆中共享变量时的可见性保障机制。
问题:JMM中的主内存和工作内存分别对应实际硬件的什么组件?
答案:主内存对应物理内存(存放共享变量,如堆中的对象字段);工作内存对应CPU的高速缓存和寄存器(线程操作共享变量时,会先拷贝到工作内存,操作后再同步回主内存)。这也是并发问题的根源——CPU缓存导致可见性问题,指令重排序导致有序性问题。
二、核心特性题
问题:请解释JMM中的可见性、原子性、有序性,各举一个实际代码场景说明。
答案:
可见性:一个线程修改共享变量后,其他线程能立即看到修改结果。场景:线程A修改布尔变量flag=true,线程B循环判断flag,若未加volatile,线程B可能一直看不到修改(CPU缓存未刷新)。
原子性:一个操作或多个操作要么全执行,要么全不执行,不可分割。场景:i++(读取、加1、写入),多线程下可能出现计数不准(中间步骤被打断)。
有序性:程序执行顺序按代码逻辑推进,禁止指令重排序导致的执行混乱。场景:单例模式双重检查锁,若未给实例加volatile,可能出现“实例已赋值但未初始化完成”的情况(指令重排序导致)。
问题:volatile关键字在JMM中是如何保证可见性和有序性的?为什么不能保证原子性?
答案:
可见性:线程修改volatile变量后,会立即将工作内存中的值刷新到主内存;其他线程读取时,会直接从主内存加载,跳过工作内存缓存。
有序性:通过“内存屏障”禁止指令重排序——volatile变量前后的指令不能跨越该变量重排,保证代码逻辑顺序。
不能保证原子性:volatile仅解决“读/写单个变量”的可见性和有序性,但复合操作(如i++、a+=b)仍需多步执行,线程切换时会被打断。比如两个线程同时执行volatileinti=0;i++,可能都读取到0,最终结果为1而非2。
三、实战应用题
问题:synchronized和volatile的区别与适用场景?
答案:
|维度|volatile|synchronized|
|--------------|-------------------------|-------------------------|
|保证特性|可见性、有序性|可见性、有序性、原子性|
|锁粒度|无锁(轻量级)|悲观锁(对象锁/类锁)|
|性能|开销极低,无阻塞|开销较高,可能阻塞|
|适用场景|单个变量的读/写同步|复合操作、代码块同步|
示例:简单的状态标记(如flag控制线程启停)用volatile;多线程累加计数、修改复杂对象属性用synchronized或AtomicInteger。
问题:JMM中的happens-before原则是什么?列举3个常用原则并说明。
答案:happens-before是JMM的核心规则,定义了两个操作的偏序关系——若Ahappens-beforeB,则A的执行结果对B可见,且A的执行顺序在B之前。常用原则:
程序次序原则:同一线程内,代码按书写顺序执行(单个线程内指令重排序不影响逻辑结果)。
volatile变量原则:对volatile变量的写操作,happens-before后续对该变量的读操作。
锁原则:解锁操作happens-before后续对同一锁的加锁操作(如线程A解锁,线程B加锁后能看到A的修改)。
线程启动原则:Thread.start()happens-before线程内的所有操作。
问题:为什么单例模式的双重检查锁(DCL)必须给实例加volatile?
答案:未加volatile时,可能出现“指令重排序”导致的空指针异常:
//错误写法
publicclassSingleton{
privatestaticSingletoninstance;//未加v
原创力文档


文档评论(0)