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

彻底理解volatile

  volatile原理
  在Java并发编程中synchronized和volatile扮演者重要的角色,volatile是轻量级的synchronized,它在多处理器开发中保证了共享变量的可见性和程序执行的有序性。如果volatile使用恰当的话,它比** **synchronized的使用和执行成本更低,因为它不会引起线程上下文切换和调度。 我们了解一下计算机,例如在我们工作当中大多数都是多核,由于CPU和物理主存速度不一致问题,为了解决CPU读取内存指令和数据效率问题,诞生了CPU高速缓存。
  private volatile instance = new Singleton();
  在生成汇编代码时会在volatile修饰的共享变量进行写操作的时候会多出Lock前缀的指令 ,Lock前缀指令在多核处理器下会发生两件事。  将当前处理器缓存行的数据写回系统内存;  这个写回内存的操作会使得其他CPU里缓存了该内存地址的数据无效
  为了提高处理器速度,首先处理器不直接和内存进行通信,而是先将系统内存的数据读到高速缓存(L1,L2,L3)后再进行操作,但是操作何时会写到内存,如果对声明volatile的变量进行写操作,JVM 就会向处理器发送一条Lock前缀的指令,将这个变量所在缓存行的数据写到系统内存。但是就算写到内存,如果其他处理器存在的值还是旧的,再执行计算操作就会有问题。所以,在多处理器下,为了保证各处理器的缓存是一致的,就会实现缓存一致性协议,每个处理器通过嗅探在总线上传播的数据来检查自己缓存的值是不是过期了,当处理器发现自己缓存行对应的内存地址别修改,就会将当前处理器的缓存行设置为无效状态,当处理器对这个数据进行修改操作的时候,会重新从系统内存中把数据读到处理器缓存里。 因此,我们得出一下结论:  Lock前缀的指令会引起处理器缓存写回内存;  一个处理器的缓存回写到内存会导致其他处理器的缓存失效;  当处理器发现本地缓存失效后,就会从内存中重读该变量数据,即可以获取当前最新值。
  这样针对volatile变量通过这样的机制就使得每个线程都能获得该变量的最新值,即可见性。  可见性
  那么下面我们通过代码证明volatile如何保证可见性? 保证不同线程对这个变量进行操作时的可见性,即变量一旦改变所有线程立即可以看到  /**  * 保证可见性  */ public class ResourceData {      // voliate 关键字能保证变量的可见性,多个线程修改同一个变量时,一个线程修改完,另一个线程获取到的是修改之后的值。     private volatile int number = 0;      public void add() {         this.number = 10;     }       public static void main(String[] args) {         ResourceData resourceData = new ResourceData();          new Thread(() -> {             System.out.println(Thread.currentThread().getName() + "	 come in ");             try {                 TimeUnit.SECONDS.sleep(3);                 resourceData.add();                 System.out.println(Thread.currentThread().getName() + "	 update number value " + resourceData.number);             } catch (InterruptedException e) {                 e.printStackTrace();             }         }, "AA").start();           // 第二个线程是main         while (resourceData.number==0) {          }         System.out.println(Thread.currentThread().getName()+"	 mission is over ,main get number value :" +resourceData.number);     } } AA  come in  AA  update number value 10
  如果共享变量不加volatile ,没有可见性,程序无法停止,加了volatile保证可见性,程序可以停止。
  原理解释:  没有添加volatile关键字,线程A对共享变量改变了以后将number修改为10,主线程(线程B)访问number的值还是0,这就是不可见。  添加volatile之后,线程A对共享数据进行了改变以后,那么main线程再次访问,number的值就是改变之后的number=10  原子性
  不保证原子性,代码实现:  /**  * 不保证原子性  */ public class ResourceData2 {      // volatile 关键字不能保证变量的原子性,当多个线程修改一个变量的时候可能回出现写丢失的情况。     // 如何保证数据的原子性呢     private volatile int number = 0;      // AtomicInteger 包装类可以保证变量的原子性     AtomicInteger atomicInteger = new AtomicInteger();     public  void addAtomic() {         atomicInteger.getAndIncrement();     }      public void add() {         number++;     }      public static void main(String[] args) {         ResourceData2 resourceData = new ResourceData2();         for (int i = 0; i <20 ; i++) {             new Thread(()-> {                     for (int j = 0; j < 1000; j++) {                         resourceData.add();                         resourceData.addAtomic();                     }             },String.valueOf(i)).start();         }          // 等待上面的线程全部计算完,再通过main线程获取最终的结果         while (Thread.activeCount()>2) {             // 指main 和Gc             Thread.yield();         }         System.out.println(Thread.currentThread().getName()+"	 finally number value :"                 +resourceData.number+"	 finally atomicInteger value :"+resourceData.atomicInteger);     } } main  finally number value :19778  finally atomicInteger value :20000
  预期结果是:20000,但是实际结果是:19778,那么是什么原因导致的呢?  首先对于一读一写操作,不会有数据问题 ,因为假设主内存的共享变量number=1,需要对主内存的number++处理,对于两个线程T1、T2如果是一读一写的操作是不会有数据丢失的情况,某一时刻,t1抢到CPU的执行权,将共享数据读回T1的工作内存,进行number++的操作,这个时候number=2,将2从工作内存写回到主内存中。写回后马上通知T2线程,将number=2读到T2的工作线程,所以不会造成数据丢失问题。  对于两个写,会出现数据问题,假设主内存的共享变量number=0,需要对主内存进行10次的number++处理,最终的结果就是10,对于两个线程T1、T2如果是两个写的操作会造成数据丢失的情况,T1和T2将主内存的共享数据读取到各自的工作内存去,某一时刻,T1线程抢到CPU的执行权,进行number++的处理,将工作内存中的number=1写回到主内存中,就在这一刻,T2也抢到CPU执行权,进行number++的处理,这个时候number++后的结果也等于1,T1将number=1写回到主内存中去,并通知T2线程,将主内存中的number=1读到T2的工作内存中去,这个时候对于T2,它之前也进行了一次number++的操作将会无效,回重新进行一次number++的操作。这也数据也就写丢了一次,那么10次number++后的结果也就不会等于10。  禁止指令重排
  重排序是指编译器和处理器为了优化程序性能而对指令序列进行重新排序的一种手段,有时候会改变程序语句的先后顺序(不存在数据依赖关系,可以重排序;存在数据依赖关系,禁止重排序) 重排序的分类和执行流程  编译器优化的重排序:编译器在不改变单线程串行语义的前提下,可以重新调整指令的执行顺序  指令级并行的重排序:处理器使用指令级并行技术来将多条指令重叠执行,若不存在数据依赖性,处理器可以改变语句对应机器指令的执行顺序  内存系统的重排序:由于处理器使用缓存和读/写缓冲区,这使得加载和存储操作看上去可能是乱序执行
  数据依赖性:若两个操作访问同一变量,且这两个操作中有一个为写操作,此时两操作间就存在数据依赖性(存在数据依赖关系,会禁止重排序,因为会导致程序运行结果不同), 如果不存在依赖关系,可以重新排序。
  如果本文对你有帮助的话,欢迎点赞,非常感谢,欢迎关注公众号: 阿福聊编程

全球排名直线超车,中国排名斩获多冠!树根互联凭什么?数字化转型时代,工业互联网平台价值凸显,在驱动工业制造和信息化的深度融合方面发挥着重要作用,但是我国整个工业数字化转型的进程仍不够乐观,还亟需更多优秀的工业互联网平台企业,以践行诠再次反转!中美突然达成涉及67国WTO内部多边协定,态势有利中国根据BBC法新社等境外知名媒体日前发布的消息,服务贸易国内规制联合声明倡议在经过4年的磋商之后正式予以公布。中国美国英国等67国12月初在世界贸易组织(WTO)框架内,宣布服务贸易5万亿补贴够生孩子吗?专家不想生的还是不生本文来源时代财经作者余思毅近日,梁建章任泽平等人口经济学家发布了中国人口预测报告2021版,指出,如果只按目前这种力度来鼓励生育,中国毫无疑问将在几十年内成为老龄化程度和人口萎缩最让全世界永远充满光明!中国10年后在太空造一个小太阳,能源无穷据英国媒体近日报道,中国西南部的一座山城每年有三分之的时间被雾气笼罩,乍看起来这里并非建设太阳能发电站的理想之地。但科学家们说,这里很快将建成中国首个测试一项革命性技术的实验设施。三星力压苹果小米,蝉联九年全球第一,为何在中国却无人问津?2021年即将收尾,各大手机厂商经历了一年激烈的角逐,局势差不多已经定了。近日,国际权威机构Gartner公布了今年第三季度全球智能手机销量排行,其中三星凭着20。2的市场份额,力收入近3000亿,用户超6亿!2021中国游戏业年报出炉wuhu专题文老胡12月15日,由中国音像与数字出版协会指导,游戏工委和伽马数据主办的中国游戏产业年会产业趋势发展论坛在广州召开。论坛以跨界破壁创新融合为主题,在现场发布了2022李霄鹏迎来晴天霹雳!洛国富摊牌最终去向,从此远离中国足球北京时间12月19日,有媒体曝光对国足表达忠诚的归化球员洛国富已经忍无可忍,有了想法打算回巴西,这体现了足协管理可谓是一地鸡毛,这究竟是怎么回事呢?中超联赛第二阶段比赛开启后,国足怀孕期间,孕妈若发现身体有这些异常感觉,别犹豫,尽快去产检准妈妈们在怀孕期间,可以说身体是最娇贵的,特别容易因为季节环境以及个人的卫生健康等因素导致准妈妈们的身体出现一些异常的情况。而且最主要的是孕妈们的腹中还孕育着一个鲜活的生命,如果身辽宁一妈妈花40块买来一堆别人不要的卡片,儿子开心得手舞足蹈导语妈妈买来一堆别人不要的卡片,儿子看到后开心的手舞足蹈,得知价格以后网友沉默了。近日,在辽宁丹东,一个小男孩吵着让妈妈给自己买卡片,妈妈无奈之下带着孩子来到了玩具店,本来是想给孩游历山川格凸胜景(2)大穿洞,又名燕子洞,洞口高116米,宽25米,洞口形状很像拱门,比著名的利川腾龙洞口还高三十几米。当地人也叫该洞为燕王宫,每年从农历的清明到重阳,当数十万燕子回来时,就能看到万燕归3000块钱人民币在缅甸能干啥?够不够娶一个老婆现如今旅游慢慢地变成了一种趋势,国内的游客可能会根据自己的需求,选择在国内或者是去国外游玩。(此处已添加小程序,请到今日头条客户端查看)当他们去国外游玩的时候,可能有些小伙伴会选择
老徐谈茶第293期老徐带你了解名山名寨系列之同庆河今天继续和大家聊名山名寨系列同庆河。知道易武瑶家三寨的茶友估计并不多,但提到弯弓刮风寨同庆河这三个茶大家应该都挺熟的吧!它们三个就是瑶家三寨著名的山头,在普洱茶界中应该算是如雷贯耳坐火车翻越喜马拉雅山脉,魔幻通往现实在喜马拉雅山脉面前,地球上所有山峦都会黯然无光。绵延2450公里的一众山峰皆高耸入云,平均海拔突破7000米,其间矗立着世界最高峰,令人望而却步。古人常常将一些难以逾越的山脉与河流这些遗址保护公园,见证了北京的历史变迁北京晚报五色土作者景长顺故都北京,现在有大大小小的公园1090个,称得上规模宏大,类别齐全,特色鲜明,底蕴深厚。这为数众多的公园里,有不少遗址保护公园,分别和古代一段时期的王朝有着自驾河北内蒙新疆(41)9月1号,不知不觉已经进入九月份了。今天按计划去正镶白旗。我们导航走国道。207国道路况不错,也很通畅。可是走到一半的时候,突然被拦住,说前面修路,必须上高速。没办法,走高速吧。还在鼋头渚的岸边这是四月的清晨,雾蒙蒙,今晨的太湖特别宁静,潮水卷起细细的波浪向岸边涌来。湖面上有一层薄薄的雾霭,远处的景色被雾笼罩,分不清水与天。年轻的我与妻子坐在一块硕大的巨石上面,听着湖水轻中国蜜月旅行产业政府战略管理与区域发展战略研究咨询报告蜜月旅游产业消费需求及发展趋势的分析与研究据悉,蜜月游基本成为新婚人群的刚性需求。随着90后消费者对婚纱照和婚礼的个性化追求,海外婚纱照和婚礼逐渐流行起来。传统跟团游是蜜月客户的最藏在香山公园里的老牌餐厅藏在香山公园内的一家国营餐厅,开了有30多年了。可以在园内悠然自得的享受美食,欣赏美景旁边就是香山公园的眼镜湖。餐厅有露天位和室内位,提供早餐(糖油饼很火)。糖醋里脊必点菜,传统手官厅水库附近观澜小洱海项目怎么样?官厅水库附近观澜小洱海项目怎么样?今天继续和大家讨论一下吧,有不一样见解的欢迎评论沟通哦在我心里理解中的家,是一种远离繁华且静谧于岁月中的安好,每天清晨睡醒以后都可以伴随清风徐徐来9月最佳旅游地推荐迎接层林尽染五彩斑斓的秋光夏日的余热已在悄然散去,秋色将至,国内几地已迎来2022年的初雪,这抹凉爽羡煞了还挣扎在30度高温的南方地区。随着秋意渐浓,气温逐步走低,赶紧把秋游计划安排起来,以免错过这层林尽染京城夜生活精彩夜游北京地图来袭!开启你的初秋夜游之旅说起京城夜生活您会想到哪?今天,迷妹就和大家分享几个夜游好去处,一起来感受下北京夜晚的魅力!北京欢乐谷如果说白天的欢乐谷是惊心动魄,那么夜晚的欢乐谷就是流连忘返!北京欢乐谷,可谓是地球位置可能被监视?太阳系暴露在附近上千个恒星系统的视野中头条创作挑战赛1。截至目前,天文学家已通过望远镜观测到4000多颗系外行星,并在这其中找到了许多可能移居的行星世界。2。由此可以看出,发现外星生命或许只是时间问题。说到这里,可能有