面试官问dcl为什么用volatile 我回答是为了禁止指令重排序,防止返回没有完成初始化的singleton对象 他一直说不对 还一直问我 我真的难受啊
全部评论
这里解释一下,volatile 的作用确实不是禁止指令重排序(虽然网上大都是这么笼统的说的) 之所以多线程会获取到未完全初始化完成的单例对象,是因为new关键字在字节码中是分三步来执行的,正是这三步的乱序造成了线程不安全的问题。volatile真正的作用是在这三步字节码前后加上内存屏障(而不是禁止重排),从而防止对象在未初始化完成就被获取
13
送花
回复
分享
发布于 2022-05-08 09:21
volatile关键字不就两个作用吗,这个不对你换保证可见性,他还说不对,你就说你TM给我解释解释,什么TMD叫dcl要用volatile
8
送花
回复
分享
发布于 2022-05-06 18:52
网易互娱
校招火热招聘中
官网直投
个人理解,你的回答是对的。先跑A线程,因为new 对象的过程不是原子的,那就可能分配了内存但没有初始化,此时跑B线程,check时因为对象分配了内存不会为null,直接返回了一个没有初始化完成的对象,然后A线程再初始完对象……所以根源在于 new 操作非原子,存在被指令重排的可能性,对象虽然只会被 new 一次而且可以成功初始化,但在 new 的过程中,其他线程可能会拿到未被初始化完成的对象。
2
送花
回复
分享
发布于 2022-05-08 10:41
保证可见性,多线程情况下,初始化立即能被看见。
1
送花
回复
分享
发布于 2022-05-02 11:22
确实是错的,应该是happens before规则
点赞
送花
回复
分享
发布于 2022-06-13 15:39
我觉得你的回答没有问题,我查了一下viotile的oracle官方文档,里面明确了是可以禁止重排序的,如果不禁止重排序,需要保证重排序的所有结果和不重排序是一样的。 官网viotile地址:https://docs.oracle.com/javase/specs/jls/se8/html/jls-8.html#jls-8.3.1.4 关于new关键字的问题:我使用idea自带的show bytecode工具查看字节码,结果如下: 后面的注释是我自己加上的 L9 // 第九个子程序 LINENUMBER 15 L9 // 第九个子程序对应代码第15行, 这行中只有new 的一句话 NEW org/short_address/org/keyword/VolatileTest // 生产对象 DUP INVOKESPECIAL org/short_address/org/keyword/VolatileTest.<init> ()V // 初始化 PUTSTATIC org/short_address/org/keyword/VolatileTest.object : Lorg/short_address/org/keyword/VolatileTest; // 把new的对象引用赋值给object对象 综上所述,我觉得楼主回答的没有问题
点赞
送花
回复
分享
发布于 2022-06-28 11:12
感觉严格来说并不是禁止指令的重排序,而是加入了读写屏障使得指令的重排序收到了一定的限制从而避免了singleton对象在创建后但是并未初始化完毕的情况下返回,只能说受限而非禁止,我认为。
点赞
送花
回复
分享
发布于 2023-11-02 20:51 浙江

相关推荐

3 19 评论
分享
牛客网
牛客企业服务