经验首页 前端设计 程序设计 Java相关 移动开发 数据库/运维 软件/图像 大数据/云计算 其他经验
当前位置:技术经验 » Java相关 » Java » 查看文章
JVM知识(三):内存模型和可见性
来源:cnblogs  作者:MoreThinking  时间:2018/11/1 9:42:58  对本文有异议

这篇文章我们将根据JVM的内存模型探索java当中变量的可见性以及不同的java指令在并发时可能发生的指令重排序的情况。来聊聊java线程对一个变量的更新怎么通知另一个线程,及volatile的作用和指令重排序的问题。

内存模型

  首先我们思考一下一个java线程要向另外一个线程进行通信,应该怎么做呢,又或者说,一个java线程对一个变量的更新怎么通知到另外一个线程呢?我们知道java当中的实例对象、数组元素都放在java堆中,java堆是共享的(这里我们把java堆称为主内存)。而每一个线程都是自己私有的内存空间(称为工作内存),如果线程1要向线程2通信,一定会经过以下类似的流程:

    

  1、线程1将自己工作内存中的X更新为1并刷新到主内存中;

  2、线程2从主内存中读取变量X=1,更新到自己的工作内存中,从而线程2读取的X就是线程1更新后的值。

从上面的流程看出线程之间的通信都需要经过主内存,而主内存与工作内存的交互,则需要java内存模型(JMM)来管理。下图演示了JMM如何管理主内存和工作内存:

当线程1需要将一个更新后的变量值刷新到主内存中时,需要经过两个步骤:

  1、工作内存执行store操作(存储操作);

  2、主内存执行write操作(写操作);

完成这两个操作即可将工作内存中的变量值刷新到主内存中,即线程1工作内存和主内存的变量值保持一致;

当线程2需要从主内存中读取变量的最新值时,同样需要经过两个步骤:

  1、主内存执行read操作,将变量值从主内存中读取出来;

  2、工作内存执行load操作,将读取出来的变量值更新到本地内存的副本;

完成这两步,线程2的变量和主内存的变量值就保持一致了。

可见性

  java中有一个关键字 volatile,它有什么用呢?(没有volatile会出现的情况举例!

  这个答案其实就在上面说java线程间通信机制中,我们想象一下,由于工作内存这个中间层的出现,线程1和线程2比如存在延迟的问题,例如线程1在工作内存中更新了变了,但是还没有刷新到主内存,而此时线程2获取到的变量值就是还未更新的变量值,又或者线程1成功将变量更新到主内存,但是线程2依然使用主键工作内存中的变量值,同样会出现问题。不管出现哪种情况都可能导致线程间的同学不能达到预期的目的。

  1. //线程1
  2. boolean stop = false; while(!stop){ doSomething(); }
  3. //线程2
  4. stop = true;

  这个例子表示线程2通过修改stop的值,来控制线程1的中断,但是在真是环境中可能会出现意想不到的结果,线程2在执行之后,线程1并没有立刻中断甚至一直不会中断。出现这种情况的原因就是线程2对线程1的变量更新无法第一时间获取到。

但是这一些等到volatile出现后,就不会出现了。volatile保证两件事情:

  1、线程1工作内存中的变量更新会强制立即写入到主内存;

  2、线程2工作内存中的变量会强制立即失效,这使得线程2必须去住线程中获取最新的变量值。

所以这就理解了volatile保证了变量的可见性。因为线程1对变量的修改能第一时间让线程2可见。 

 友情链接:直通硅谷  点职佳  北美留学生论坛

本站QQ群:前端 618073944 | Java 606181507 | Python 626812652 | C/C++ 612253063 | 微信 634508462 | 苹果 692586424 | C#/.net 182808419 | PHP 305140648 | 运维 608723728

W3xue 的所有内容仅供测试,对任何法律问题及风险不承担任何责任。通过使用本站内容随之而来的风险与本站无关。
关于我们  |  意见建议  |  捐助我们  |  报错有奖  |  广告合作、友情链接(目前9元/月)请联系QQ:27243702 沸活量
皖ICP备17017327号-2 皖公网安备34020702000426号