范文健康探索娱乐情感热点
投稿投诉
热点动态
科技财经
情感日志
励志美文
娱乐时尚
游戏搞笑
探索旅游
历史星座
健康养生
美丽育儿
范文作文
教案论文

一次群聊引发的血案

  就在不久前,读者群因为一个提问引发了激烈的讨论!
  代码如下图:
  从问题来看,大家讨论的问题的焦点在于 map 去 put 一个对象的时候,究竟会不会因为对象没有完全初始化完成而导致另外一个线程 get 的时候只是拿到了对象的引用,导致报错呢?
  从提供的代码的写法来看,是一个最基本的DCL稍微改变了的写法,在探讨map的问题之前,我想先从DCL(双重检查校验)说起。DCL的由来
  在最初的时候,我们常规的单例写法就像这样:
  很容易你就应该知道,这段代码不是线程安全的,所以有了加锁的单例方法实现。
  但是synchronized又会导致多线程下性能开销过大,虽然现在优化了,但是早期synchronized的性能是堪忧的,所以就诞生了双重检查锁定DCL的写法。先判断一次null,然后再加锁,这样第一次检查不是null的话就不需要加锁了,就可以避免synchronized的性能开销过大的问题。
  看样子问题是解决了,就很棒的样子,但是回到开头说的问题。DCL的问题
  从CPU的角度来看,instance = new Instance()可以分为分为几个步骤:分配对象内存空间执行构造方法,对象初始化instance指向分配的内存地址
  实际上,由于指令重排的问题,2、3的步骤可能会发生重排序,那么问题就发生了。
  instance先被指向内存地址,然后再执行初始化,如果此时另外一个线程来访问getInstance方法,就会拿到instance不是null,最后拿到的将是一个没有被完全初始化的对象!
  实际上,这个问题已经是大部分人都知道的DCL的一个问题了。
  因为根据Java内存模型语义来说,不管编译器和处理器怎么排序,单线程的执行结果都不能改变,只要数据没有依赖关系,就都可以重排序。
  那对上面的例子来说重排序改变了单线程下程序结果吗?并没有,因为无论线程A内是先初始化对象还是先把instance指向分配好的内存地址,对于单线程A的结果来说是没有任何改变的。
  也就是说,对于重排序的结果来说,只要保证线程B在访问对象的时候能拿到instance引用就可以,无论线程A内部初始化和执行内存地址两个步骤怎么重排序都不会影响到最终结果。
  重排序的结果只是造成了线程B拿到的是一个没有完全初始化完成的对象而已,可能这时候构造方法没有执行,拿到的对象属性可能是错误的,也有可能如果拿着这个没有完全初始化完成的对象去操作,可能会导致空指针的问题。
  所以,一般在使用DCL的时候会把变量声明为volatile ,因为volatile的语义会禁止指令重排,而本质上就是加上了内存屏障。一切都是猜测
  如果依据这个解释,来回答群内提出的问题貌似也可以解释的通。
  因为 map 在 put 的时候可以不管 new 对象时候的指令重排,只要能拿到对象引用的内存地址就可以了,所以另外一个线程如果去 get 的话就可能拿到一个空值。
  从as-if-serial的语义来看,确实不会改变单线程内的执行结果,但是还有一点说的是只要数据没有依赖关系,就都可以重排序。问题的关键点在于 put 这个到底有依赖关系吗?依赖关系怎么定义?
  如果是最简单的比如 x=1,y=2  那么我们可以认为完全没有依赖关系,可以指令重排。如果是 x=1,y=x+1  那么由于单线程内y 依赖于x ,所以不能指令重排。
  那么 map.put(key,new B(value))  呢?一道证明题
  Jcstress(Java Concurrency Stress)是一个帮助测试JVM和硬件并发正确性的工具库。
  首先,先证明DCL的问题是否确实存在,是否真的在另外的线程中能看到未完全初始化的对象。代码如下:
  通过测试代码,如果最终能输出0,1,2,3那么代表确实是能拿到未完全初始化完成的对象。
  首先对代码 mvn clean install  打包,然后执行命令:java -XX:-UseCompressedOops -XX:+UnlockDiagnosticVMOptions -XX:CompileCommand="print com.jcst.UnsafePublication_jcstress*::call" -XX:CompileCommand="inline, com.jcst.UnsafePublication::publish" -XX:+PrintAssembly -jar target/jcstress.jar -f -1 -t UnsafePublication -v > log2.txt 
  执行完成之后,查看输出结果发现问题确实存在:
  而且,通过生成的汇编指令,也可以看到发生了指令重排,引用被先赋值,对象还没有完全初始化完成。但是实际测试过程中,这个问题并不好复现,需要反复的测试才有可能拿到我们想要的结果。
  有了基础的事实之后,再继续修改代码,如果加上 map 操作还能出现这个现象的话,那么证明实际上 map 的 put 操作也是同样存在可能性的。
  如果同样我们能得到汇编的结果,put 的操作也被指令重排发生在初始化完成之前的话,那么就可以证明我们的猜测了。
  结果和我们之前预料的不太一致,无论怎么修改代码顺序,测试脚本都是执行通过。这说明 put 不会把一个没有初始化完成的对象给保存进去。
  总结
  由于指令重排发生的场景非常多而且也非常底层,目前我们能看到的资料无非就告诉我们单线程结果不能改变,数据不能有依赖性,这样的话就能指令重排。
  而我们的代码从 Java 通过 javac 编译成字节码,再经过 JIT 动态编译成机器码,从机器码再经过处理器,到缓存这些过程都可能发生指令重排。而编译器、处理器、缓存这些根据机器、硬件环境不同,又都可能造成不同的影响。
  通过DCL的已知问题和最后根据jcstress得到汇编的结果来看,由于没有改变单线程最终结果,指令重排是确实发生了。但是从 map 的 put 的结果来看,最终结论是不会,put 操作不会把一个没有初始化完成的对象保存进去。
  而我也尝试了不少其他的方式,比如打印、模拟 map 写了一个空方法,只是用到了引用对象,测试结果无一都是通过,所以大胆猜测使用了引用其实也是依赖的一种,这样就不会导致重排的发生。
  最后,如果你有更好的证实的方法,或者有不同的意见可以证实结论的错误性,欢迎拍砖打脸指正。

朱门酒肉臭,路有冻死骨!清朝的覆灭早已命中注定清朝,一个人人提起都忍不住皱眉的时代,一个让民族失去自信的时代,纵观这296年(16361912)的历史,它的故事很多很多,但让人记忆最为深刻的故事却是朝代的前半段与后半段,尤其是内蒙古一大爷坚持开报刊亭,一个月挣不到100块,最后一句话亮了近日,内蒙古包头市,一位开报刊亭的大爷在与客人闲聊时,透露出报刊亭的现状。大爷说,现在开报刊亭根本就不赚钱了,一个月还赚不到100块。可是他还是每天都准时开门,只是因为有感情了,舍疯狂的英语,疯狂的李阳这次直接家暴亲女儿因为疯狂英语,我认识了李阳,高中时代还真实的崇拜了他一把。前几年李阳家暴自己老婆着实让他疯狂了一把。可是就在这两天,李阳的前妻kim发文控诉李阳再次家暴,令人咂舌的是这次家暴对象不伍珂玥董书含输掉外战后,王靖雯成夺冠大热门,其实她也没戏2021好声音盲选即将收官,目前基本上大部分学员都已登台露面,从这些已经露面的学员的表现来看,确实有那么几位学员非常具备冠军相。首先要说的就是李克勤战队的伍珂玥,自她盲选登场到现在连胡海泉都比不过的林志炫,其实就是一个二线歌手,事实可以证明谁也不会想到,披荆斩棘的哥哥最先翻车的居然是林志炫。从第一期各位哥哥的出场来看,林志炫明显是带着光环来的,主要表现在三个方面第一,他登场时其他哥哥几乎全部起立致敬第二,初次见面请多盘点好声音史上十大美女,第十季三人上榜,陈冰不再是第一好声音举办到第十年,不仅诞生了许多唱功出众的学员,更是涌现出了许多美女学员,她们的颜值,丝毫不逊色于那些当红女明星,让人无不顿生怜香惜玉之心。今天,我们就来盘点一下好声音史上的十大好声音十年共16位导师,若要选出最强导师阵容,哪四位可上榜好声音举办了十年,每年除了来自五湖四海的学员,导师阵容也是大家很关心的话题。每季四位导师,十年就是四十人次的导师,其中不少导师都参加了多季,所以十年一共来了16位导师,他们分别是刘张淇白举纲霍尊翻唱的悟空的确很燃,但跟原唱比差距就出来了披荆斩棘的哥哥第二次公演竞演曲目公布后,哥哥们都把目光聚焦到了同一首歌上,是的,就是那首传唱度非常之高相当之经典的悟空。如果能拿到这首歌,几乎就等于赢了一半,没办法,这首歌实在是太从参加快男出道到现在,张淇为什么用了14年才火?原因有三点大概很多人都没想到,参加披荆斩棘的哥哥的三十多位哥哥中,最先走红的是名不见经传的张淇。有的人一听到张淇这个名字,不禁发出疑问他是谁?是啊,最先听到这个名字,我也很好奇,娱乐圈似乎没李荣浩真正要捧的是于梓贝,而不是有文身的王靖雯,有四点原因本季好声音第七期节目之后,学员们的水平已经显露得差不多了,谁是真正的实力派,谁是打酱油的,我们基本一目了然。要说目前争议比较大的,还是王靖雯。王靖雯2020年在某音开始拍短视频,短王靖雯为啥要戴防晒袖?吉克对李荣浩说了什么让他为于梓贝转了身说来也奇怪,王靖雯居然在上好声音之前就已经在某音积累470万粉丝,也算是一个大网红了。可我实在搞不明白,她到底哪里有吸引力,凭什么就有这么多粉丝呢?王靖雯在好声音舞台上是真不讨喜,
程潇几次宣传翻车,出道5年家人竟不知做什么?程潇最近这几次宣传有很大问题,在捐款方面怼网友已经够翻车了,结果还来了一个家里不知道她是做什么的的热搜话题。程潇入圈发展已有五年多时间,现如今提起程潇的名字相信小伙伴们一定对她很熟Mandy幼女照首曝光,分手后才发现怀孕,与洗米华永远是家人12月3日,据港媒报道,娱乐大亨洗米华与Mandy目前已经分手,然而日前Mandy接受访问却自曝去年又为洗米华生下一个女儿,还称与已有家室的洗米华永远是一家人,四胎小公主的照片首曝姚笛与家人聚餐,被男友摸头亲吻超甜,两人感情稳定疑已结婚1月5日,据媒体报道,姚笛近日携男友和家人聚餐,席间二人互动亲密,饭后一行人又去超市购物,姚笛男友全程跟在女友身后,像极了老夫老妻的相处模式,据悉此前有传闻称姚笛已经接受了男友的求2021舟山东海音乐节(时间地点门票)订票指南十月的舟山朱家尖,在为一场一年一度的盛宴筹备,这是一场仪式,也是音乐老饕钟爱的狂欢节!2021舟山东海音乐节,第九年的东海边,我们燃情72小时!舟山东海音乐节时间202110293长江六大水电站中有四座可排进世界前五,现有96台发电机同时发电长江是我国最大的河流,水能蕴藏量极其丰富,约占全国的23,干支流水能资源蕴藏量共约2。68亿千瓦,其中可开发的水能资源约1。97亿千瓦,年发电量至少可达1万亿千瓦时(度),大约相当幸运的于和伟!历史上有名的两次三顾茅庐,他都演绎了在演艺圈里,很多人都是大器晚成的,对于于和伟的认知,肯定有不少人来源于三国,那会可能是因为里面的明星大腕实在是太多了,也没有多显着他,只是觉得没有拖后腿而已,直到后面他的电视剧一部他25岁春晚一夜成名,成就刘欢毛宁,40岁意外去世死因成谜在这个陪着枫叶飘零的晚秋,才知道你不是我一生的所有。蓦然又回首,是牵强的笑容,那多少往事飘散在风中。听到这首晚秋,很多人第一印象想到的应该是毛宁,可以说晚秋这首歌成就了毛宁,但这首姚策的死因有猫腻?杜新枝怕姚策见到许妈说真相换房子还钱?杜新枝是姚策想去的,姚策前往北京实行安乐治疗意见,系在家庭群协商确认大家看完了这段由杜新枝亲口说的话有什么感想,在这里斑马就问杜新枝几个问题一为什么姚策突然去世以后,许妈连送姚策最张碧晨远走秘密生娃原因曝光,与郑爽如出一辙,受父母影响太大年关将近,娱乐圈在冲KPI,吃瓜群众都有些跟不上速度,郑爽的dy弃养风波还在持续发酵中,张碧晨和华晨宇就紧随其后,双双发文承认二人未婚育有一女,女儿都已经一岁多了,让网友大为震惊。32岁毛晓彤善良但不圣母,悲惨童年成就坚韧,一招狠治小三渣男1月31日,汪峰新歌上线,章子怡接连两天发文帮忙老公宣传,然而还是没能逃过汪峰发歌必有大瓜的定律,一大早毛晓彤和陈翔之间的爱恨情仇高挂热搜,汪峰的新歌就像歌名没有人在乎一样,真的没刺杀小说家藏着人生大秘密千万别轻视身边毫不起眼的人人民观影团刺杀小说家01。刺杀小说家是由绣春刀系列导演路阳执导,宁浩监制,雷佳音杨幂董子健于和伟郭京飞等主演的奇幻动作冒险电影。它是一部特效大片,但又与好莱坞大片保持着距离,因为它