高并发的可见性搞不明白,就不用再研发了( 三 )


描述: 在某一个线程执行到第一次检测 , 读取到instance不为null时 , instance的引用对象可能没有完成初始化 。 instance=new SingleDemo();可以被分为一下三步(伪代码):
memory = allocate();//1.分配对象内存空间instance(memory); //2.初始化对象instance = memory; //3.设置instance执行刚分配的内存地址 , 此时instance!=null指令重排是不会对有明显依赖关系的代码进行重排序的 , 我们的代码可能存在着逻辑上的先后关系 , 但JVM并无法智能识别 。 比如图中步骤2和步骤3在依赖上不存在关系 , 而且无论重排前还是重排后程序的执行结果在单线程中并没有改变串行语义执行的一致性 , 在JVM看来这种重排优化是被允许的 。 如图如果3步骤提前于步骤2 , 而instance还没有初始化完成 , 这个时候便出现A线程访问instance不为null时 , 由于instance实例尚未初始化完成 , 线程A本该获取到存在的instance实例 , 但由于错误判断获取也就造成了线程安全问题 。
单例模式volatile代码
说明:在上述代码中的SingletongDemo实例上加上【volatile】:
private static volatile SingletonDemo instance = null;有任何问题欢迎留言交流~
整理总结不易 , 如果觉得这篇文章有意思的话 , 欢迎转发、收藏 , 给我一些鼓励~
有想看的内容或者建议 , 敬请留言!
最近利用空余时间整理了一些精选Java架构学习视频和大厂项目底层知识点 , 需要的同学欢迎私信我发给你~一起学习进步!有任何问题也欢迎交流~
【高并发的可见性搞不明白,就不用再研发了】Java日记本 , 每日存档超实用的技术干货学习笔记 , 每天陪你前进一点点~