专栏电商日志财经减肥爱情
投稿投诉
爱情常识
搭配分娩
减肥两性
孕期塑形
财经教案
论文美文
日志体育
养生学堂
电商科学
头戴业界
专栏星座
用品音乐

Java并发编程初识Volatile(概念与特性)

  一、什么是Volatile概念
  volatile是Java中的关键字,用来修饰会被不同线程访问和修改的变量。volatile可以说是java虚拟机提供的最轻量级的同步机制。二、特性1、保证可见性概述
  保证不同线程对这个变量进行操作时的可见性,即变量一旦改变所有线程立即可见。代码验证publicclassVolatileSeeDemo{staticbooleanflagtrue;publicstaticvoidmain(String〔〕args){newThread((){System。out。println(Thread。currentThread()。getName()comein);while(flag){}System。out。println(Thread。currentThread()。getName()comeout);},t1)。start();线程睡眠2stry{TimeUnit。MILLISECONDS。sleep(2000);}catch(Exceptione){e。printStackTrace();}flagfalse;System。out。println(Thread。currentThread()。getName()修改完成);}}
  输出结果:程序无法正常结束
  线程t1中为何看不到被主线程main修改为false的flag的值?
  问题可能:主线程修改了flag之后没有将其刷新到主内存,所以t1线程看不到。主线程将flag刷新到了主内存,但是t1一直读取的是自己工作内存中flag的值,没有去主内存中更新获取flag最新的值。
  解析
  由于普通变量没有可见性,无法感知结果的变化,主线程将flag刷新到了主内存,但是t1一直读取的是自己工作内存中flag的值,没有去主内存中更新获取flag最新的值。故while里面的flag始终是ture,因此导致程序一直在while循环中。
  下面用volatile修饰flagpublicclassVolatileSeeDemo{staticvolatilebooleanflagtrue;publicstaticvoidmain(String〔〕args){newThread((){System。out。println(Thread。currentThread()。getName()comein);while(flag){}System。out。println(Thread。currentThread()。getName()comeout);},t1)。start();线程睡眠2stry{TimeUnit。MILLISECONDS。sleep(2000);}catch(Exceptione){e。printStackTrace();}flagfalse;System。out。println(Thread。currentThread()。getName()修改完成);}}
  运行结果:程序正常结束
  解释
  由于flag被volatile修饰,故其具有可见性,flag的每一次修改都会被发现,flag由true变为false,循环结束。volatile修改的变量特点线程中读取的时候,每次读取都会去主内存中读取共享变量最新的值,然后将其复制到工作内存。线程中修改了工作内存中变量的副本,修改之后会立即刷新到主内存。volatile变量的读写过程
  Java内存模型中定义的8种工作内存与主内存之间的原子操作
  read(读取)load(加载)use(使用)assign(赋值)store(存储)write(写入)lock(锁定)unlock(解锁)
  read:作用于主内存,将变量的值从主内存传输到工作内存,主内存到工作内存
  load:作用于工作内存,将read从主内存传输的变量值放入工作内存变量副本中,即数据加载
  use:作用于工作内存,将工作内存变量副本的值传递给执行引擎,每当JVM遇到需要该变量的字节码指令时会执行该操作
  assign:作用于工作内存,将从执行引擎接收到的值赋值给工作内存变量,每当JVM遇到一个给变量赋值字节码指令时会执行该操作
  store:作用于工作内存,将赋值完毕的工作变量的值写回给主内存
  write:作用于主内存,将store传输过来的变量值赋值给主内存中的变量
  由于上述只能保证单条指令的原子性,针对多条指令的组合性原子保证,没有大面积加锁,所以,JVM提供了另外两个原子指令:
  lock:作用于主内存,将一个变量标记为一个线程独占的状态,只是写时候加锁,就只是锁了写变量的过程。
  unlock:作用于主内存,把一个处于锁定状态的变量释放,然后才能被其他线程占用2、没有原子性概述
  原子性指的是一个操作是不可中断的,即使是在多线程环境下,一个操作一旦开始就不会被其他线程影响。代码验证classMyNumber{staticintnumber0;publicstaticvoidadd(){number;}}publicclassVolatileNoAtomicDemo{publicstaticvoidmain(String〔〕args){for(inti0;i10;i){newThread((){for(inti10;i11000;i1){MyNumber。add();}},String。valueOf(i))。start();}暂停3s线程try{TimeUnit。MILLISECONDS。sleep(3000);}catch(Exceptione){e。printStackTrace();}System。out。println(Thread。currentThread()。getName()myNumber:MyNumber。number);}}
  输出结果
  理论上是输出1010001w的,为什么这里只有4312呢?字节码角度分析
  原子性指的是一个操作是不可中断的,即使是在多线程环境下,一个操作一旦开始就不会被其他线程影响。publicvoidadd(){i;不具备原子性,该操作是先读取值,然后写回一个新值,相当于原来的值加上1,分3步完成}
  如果第二个线程在第一个线程读取旧值和写回新值期间读取i的域值,那么第二个线程就会与第一个线程一起看到同一个值,
  并执行相同值的加1操作,这也就造成了线程安全失败(即一个线程更新数据完成后去刷新主内存,导致正在修改数据的线程直接结束,因此造成部分i失效,而循环次数一直在累加),因此对于add方法必须使用synchronized修饰,以便保证线程安全。不保证原子性原因
  多线程环境下,数据计算和数据赋值操作可能多次出现,即操作非原子。若数据在加载之后,若主内存count变量发生修改之后,由于线程工作内存中的值在此前已经加载,从而不会对变更操作做出相应变化,即私有内存和公共内存中变量不同步,进而导致数据不一致。
  对于volatile变量,JVM只是保证从主内存加载到线程工作内存的值是最新的,也就是数据加载时是最新的。
  由此可见volatile解决的是变量读时的可见性问题,但无法保证原子性,对于多线程修改共享变量的场景必须使用加锁同步既然一修改就是可见,为什么还不能保证原子性?
  volatile主要是对其中部分指令做了处理
  要use(使用)一个变量的时候必需load(载入),要载入的时候必需从主内存read(读取)这样就解决了读的可见性。
  写操作是把assign和store做了关联(在assign(赋值)后必需store(存储))。store(存储)后write(写入)。
  也就是做到了给一个变量赋值的时候一串关联指令直接把变量值写到主内存。
  就这样通过用的时候直接从主内存取,在赋值到直接写回主内存做到了内存可见性。注意蓝色框框的间隙o()o
  总结
  读取赋值一个volatile变量的情况
  readloaduse和assignstorewrite成为了两个不可分割的原子操作,但是在use和assign之间依然有极小的一段真空期,有可能变量会被其他线程读取,导致写丢失一次。。。o()o
  但是无论在哪一个时间点主内存的变量和任一工作内存的变量的值都是相等的。这个特性就导致了volatile变量不适合参与到依赖当前值的运算,如ii1;i;之类的那么依靠可见性的特点volatile可以用在哪些地方呢?通常volatile用做保存某个状态的boolean值orint值。
  《深入理解Java虚拟机》提到:
  3、禁止指令重排概述
  指令重排序是指编译器或CPU为了优化程序的执行性能而对指令进行重新排序的一种手段,重排序会带来可见性问题,所以在多线程开发中必须要关注并规避重排序。
  从源代码到最终运行的指令,会经过如下两个阶段的重排序。
  第一阶段,编译器重排序,就是在编译过程中,编译器根据上下文分析对指令进行重排序,目的是减少CPU和内存的交互,重排序之后尽可能保证CPU从寄存器或缓存行中读取数据。从CPU层面来说,避免了处理器每次都去内存中加载stop,减少了处理器和内存的交互开销。
  第二阶段,处理器重排序,处理器重排序分为两个部分。
  并行指令集重排序,这是处理器优化的一种,处理器可以改变指令的执行顺序。
  内存系统重排序,这是处理器引入StoreBuffer缓冲区延时写入产生的指令执行顺序不一致的问题。volatile有关的禁止指令重排的行为
  四大屏障的插入情况
  代码模拟
  模拟一个单线程,什么顺序读?什么顺序写?publicclassVolatileTest{inti0;volatilebooleanflagfalse;publicvoidwrite(){i2;flagtrue;}publicvoidread(){if(flag){System。out。println(ii);}}}
  在每一个volatile写操作前面插入一个StoreStore屏障在每一个volatile写操作后面插入一个StoreLoad屏障在每一个volatile读操作后面插入一个LoadLoad屏障在每一个volatile读操作后面插入一个LoadStore屏障

10月销量出炉,这些车凭啥销量暴涨?Hello大家好!10月份的销量榜单出炉了,比亚迪依然是最大的亮点,整个品牌销量超过20万辆。啥概念呢?曾经常年排名销量第一的一汽大众销量也只有13万多辆,也就是说比亚迪以绝对的优发展个人碳账户需完善机制来源经济日报近日,中信银行基于绿色金融体系打造的中信碳账户迎来升级,不仅中信银行的银行卡持卡人可以注册,其他银行客户也可以注册。目前,碳账户的应用主要基于碳账户下个人或企业生活生产刘诗雯拿到新身份后又要升官?国乒迎来2大赛事,4主力冲击新高度近期,刘诗雯作为国乒老将虽然离开了赛场,但仍然从事和乒乓球相关性较高的工作,就在近期刘诗雯成功当选国际乒联运动员委员会委员,并且从国际乒联给出的消息来看,后续刘诗雯等人还会参加12点评西方历史中的大事件1一波希战争这场战争是游牧文明与海洋文明之间的对抗,也是集权专制对民主的城邦两种不同制度之间的比拚。波斯帝国是进攻方,无论从哪方面说都占有优势希腊城邦靠海军的强大全民高昂的斗志才勉强日本VS加拿大日本历史战绩日本历史战绩在本届世界杯上,日本队一共参加了12场比赛,其中10场比赛是在主场进行。球队取得了4胜2平2负的战绩,表现还算不错,但是与同组的加拿大队相比则有些不遑多让。从历史战绩来利拉德22分11助攻开拓者胜马刺,波尔特尔空砍生涯新高开拓者主场117110击败马刺。瓦塞尔上来两记三分,凯尔登约翰逊续上远投,波尔特尔连拿3球,马刺164开局。谢尔顿夏普格兰特两记远投止血,利拉德连续突破,助攻尤班克斯空接扣篮,开拓见证历史!阿尔忒弥斯1号成功发射1969年7月,阿姆斯特朗成为了第一个登上月球的人类,距今已经过去了整整53年,人类依旧没能重新登上月球。2012年,NASA提出了阿尔忒弥斯计划,阿尔忒弥斯1号原定于2017年发猛士,成就中国品牌新高度撰文吴静编辑张南设计师玉超今年9月,新能源乘用车零售渗透率首次超过30,成为汽车行业发展史上的里程碑事件。当新能源车渗透率屡创新高,新能源市场的消费结构也逐渐从哑铃型向纺锤型加速优粮农组织全球粮食进口将达到历史最高水平粮农组织全球粮食进口将达到历史最高水平粮农组织AmiVitale冲突人口增长迅速和严重依赖粮食进口对近东和北非的粮食安全构成严峻挑战联合国粮食及农业组织(粮农组织)在今天发布的一份中国大天鹅之乡山东荣成迎来鸟类迁徙高峰山东荣成迎来鸟类迁徙高峰,越冬大天鹅成为一道美丽风景。李信君摄中新网山东荣成11月21日电(记者杨兵)记者21日从山东荣成大天鹅国家级自然保护区获悉,目前该保护区内已观测到近500藏水入疆大水库之库木库里沙漠阿尔金山自然保护区位于新疆巴音郭楞蒙古自治州若羌县境内,与青海西藏甘肃交界,面积45000平方公里,平均海拔4600米以上。藏水入疆大水库之库木库里沙漠阿尔金山与可可西里罗布泊羌塘
30岁辞职复刻了不起的盖茨比,她做出了绝无仅有的一家店不如跳舞。文易琬玉编辑范婷婷提起古着,大部分人会联想到,密密麻麻的货架上,没有相同的两件衣服,喜爱古着的人从来不说买,都是用淘来表达发现的乐趣。在人们习惯于抄作业来安排穿搭的今天,最美鱼尾婚纱盛产地!这8个以色列婚纱品牌你要知鱼尾婚纱一直以来都是无数女人向往的款式。而以色列就是一个盛产美人鱼的国家,这个国家的艺术市场很有活力,政府也极为鼓励和支持艺术创造。从四大时装周婚纱周以及红地毡出镜率,在数量上创造还你好脸色,用昔颜洗脸让你告别油腻,倍有面子颜值当道的时代,不得不感慨这个时代在变化!人们也越来越注重护肤,其实护肤用得最多的还是洁面产品,今天就给大家推荐一款平价又好用的昔颜灵芝舒润洁面乳。其实很多人在选择护肤品的时候都面11月凤凰精选PHOENIXTOPSGucciHorsebit1955导演江唯顺沈增伟摄影林嘉杰GregLinJiajie编辑陆爱华心旅人对内心世界的探寻,回归自我的诗意旅程。在人生旅程中,每次向外的全新出发,同样是狂妄自大!日本球星喊出世界杯夺冠宣言,网友日本民族的狭隘卡塔尔世界杯马上就要开幕了,粉丝们非常期待本届世界杯,大家也都在猜测到底哪支球队能够拿到冠军。目前来看,巴西队阿根廷队以及欧洲的法国队德国队西班牙队等球队,都非常有机会夺得冠军。如安帅巴尔韦德有能力取得更多进球拉莫斯应该参加世界杯直播吧11月3日讯在今日凌晨进行的一场欧冠小组赛中,皇马51击败凯尔特人。赛后在新闻发布会上,皇马主帅安切洛蒂表示,球队从一开始就很好地投入到比赛中。关于本场比赛打进5球安切洛蒂这世界杯开赛在即,谁能夺冠2022年世界杯开赛在即,这一届大力神杯会花落谁家?是传统强队巴西法国阿根廷意大利,还是球员身价实力猛进的英格兰比利时?1阿根廷本届世界杯有可能是莱昂内尔梅西的最后一次世界杯。他正英媒世界杯前罗梅罗无法为热刺出战,预计能赶上阿根廷战沙特直播吧11月3日讯伦敦标准晚报今日更新了热刺的伤情,他们表示克里斯蒂安罗梅罗将无法在世界杯前参加热刺的比赛,他预计能赶上阿根廷对阵沙特阿拉伯的比赛。最近4场比赛,罗梅罗因为小腿拉伤101!见证中超起落,世界杯中超外援数骤降,泰山队成遮羞布卡塔尔世界杯日益临近,参加队伍大名单逐渐浮出水面,以往国内球迷看世界杯,除了支持自己喜欢的主队之外,还会关注一些在中超效力的球员,虽然看不到国足的身影,但是能够看到中超元素也算是有46694台,9月销量稳居榜首,ModelY为何如此受到宠爱?特斯拉这个品牌想必大家都耳目濡染,在新能源迅速发展中,各品牌竞争激烈,而在这个时候特斯拉的地位依然难以撼动,在九月份新能源销售榜中依然排列第一,这是为什么呢?今天小编就带大家来看一凌晨重磅!美联储加息75基点,美股黄金跳水,道指收跌超500点隔夜,市场迎来美联储加息公布,在盼来放缓加息的信号同时,也迎来美联储主席鲍威尔的鹰派态度。利率决议公布后美股一度拉升,但尾盘跳水,对利率敏感的纳指暴跌逾3,欧股整体小幅下跌,美元指
友情链接:快好找快生活快百科快传网中准网文好找聚热点快软网