问题描述
我在学习volatile的时候,知道它的作用是保证线程的可见性,意思是说当共享变量发生改变时,其它线程可以见。但我不明白其它线程可见是什么意思? 例如共享变量x=0加了volatile这个关键字; A,B两个线程 A读到x=0; B也读到x=0; A做了加一操作,此时x=1。那么B线程也应该知道x=1; 可是B做加一操作时,x也等于1。 那么我想知道这个B线程知道了x已经改变是什么意思?最好有个volatile例子能说明下。 我突然想到是这个可能: 因为x=x+1不是原子操作,分二个步骤,加操作和赋值操作。 当B的加操作比A线程快一步,但B的赋值操作比A线程慢一步时 B已经用0做完了加操作得到的结果是1,但是没赋值给x。 A已经做完了加操作,x值此时已经更新到主内存中。 按照可见性,B重新读取x=1。此时B线程内x=1,是从主内存中更新的。 再做赋值操作把B线程做的加操作结果赋值给x,x=1。 所以出现2个1。 不知道我突然想出的步骤是不是正确的,希望大家指导。 问题补充: 我在学习volatile的时候,知道它的作用是保证线程的可见性,意思是说当共享变量发生改变时,其它线程可以见。但我不明白其它线程可见是什么意思? 例如共享变量x=0加了volatile这个关键字; A,B两个线程 A读到x=0; B也读到x=0; A做了加一操作,此时x=1。那么B线程也应该知道x=1; 可是B做加一操作时,x也等于1。 那么我想知道这个B线程知道了x已经改变是什么意思?最好有个volatile例子能说明下。 我突然想到是这个可能: 因为x=x+1不是原子操作,分二个步骤,加操作和赋值操作。 当B的加操作比A线程快一步,但B的赋值操作比A线程慢一步时 B已经用0做完了加操作得到的结果是1,但是没赋值给x。 A已经做完了加操作,x值此时已经更新到主内存中。 按照可见性,B重新读取x=1。此时B线程内x=1,是从主内存中更新的。 再做赋值操作把B线程做的加操作结果赋值给x,x=1。 所以出现2个1。 不知道我突然想出的步骤是不是正确的,希望大家指导。
解决方案
你自己回答到了x=x+1确实不是原子操作所以可能出现两个1x++,++x等都不是原子操作
解决方案二:
不加volatile A加1 B可能读到的还是0,这在高并发情况下会出现。因为有可能会去读一级二级缓存。volatile使编译器产生的汇编指令, 仅仅从主存操作数据.这样就保证每次都是最新的数据不存在缓存数据。但是不能保证线程间同步,也就是说A加1跟B加1可能同时发生,也就是x+1这个操作可能被多个线程同时执行。这个是volatile不能保证的。
解决方案三:
A做了加一操作,此时x=1。那么B线程也应该知道x=1; B知道是有时间间隔的,因为线程间的内存需要先同步到主内存,再同步到其他各个线程的内存上的,这些操作虽然很快,但在多线程下还是有时间 间隔的
解决方案四:
当然要是想深入些可以看看这篇http://www.ibm.com/developerworks/cn/java/j-jtp02244/
解决方案五:
这个跟JAVA的内存模型关系比较大每个线程都有自己的内存一个共享变量(没有被VOLATILE修饰时),主内存,A线程内存,B线程内存都会有一份的(他们之间的同步由虚拟机处理,并且需要消耗时间 ,假设这里有A,B两个线程)如果被VOLATILE修饰后,这个共享变量就只在主内存,而A线程和B线程内存都不会存放这个共享变量,所以当A线程修改变量时直接操作主内存,B线程读变量时也直接操作主内存,这样B就可以第一时间 知道变量发生变化了你可以看看这篇文章 http://jiangzhengjun.iteye.com/blog/652532