可以看一下我的另一篇总结 JVM运行时数据区与JVM堆内存模型小结


推荐一篇文章,尚学堂的 Java内存模型深度解读

不方便全文转载,就摘录下吧。

以往的认知都是以基本类型、引用类型、常量、方法等来区分堆栈以及方法区常量池 -- 嗯,个人认知。

但这篇文章却刷新了认知:

1、JVM内存分为堆、线程栈。每个JVM线程都有自己的线程栈,其中存的是线程相关的信息(调用方法就会有线程?)。--主要是这点,其他的仍然相通。但不确定是否只有堆栈。

2、线程栈存储的都是变量的私有副本,线程栈之间只能有私有副本的值拷贝传递,而不能有私有副本的共享!(务必理解此时引用类型的值拷贝是指拷贝引用,而非具体的对象)

3、静态成员变量跟随着类定义一起也存放在堆上!

计算机的硬件架构(简化示意):

通常情况下,当一个CPU需要读取主存时,它会将主存的部分读到CPU缓存中。它甚至可能将缓存中的部分内容读到它的内部寄存器中,然后在寄存器中执行操作。当CPU需要将结果写回到主存中去时,它会将其内部寄存器的值刷新到缓存中,然后在某个时间点将值刷新回主存。-- 关键,不是实时刷新。

Java内存模型与硬件内存架构之间存在差异。硬件内存架构没有区分线程栈和堆。对于硬件,所有的线程栈和堆都分布在主内中。部分线程栈和堆可能有时候会出现在CPU缓存中和CPU内部的寄存器中。如下:

可能导致的问题:

缓存之间不能直接交换数据,必须通过主存。而缓存与主存之间并非实时同步。所以,多线程时,当线程栈建立在缓存上,而堆建立在主存上时,彼此之间的数据是不同步的。

1、当多个线程共享一个对象时,一个线程进行修改操作,对另一个线程来说可能是不可见的。

2、当多个线程共享一个对象时,两个线程都进行修改操作,竞争关系。

解决办法:

针对不可见情况volatile 关键字可以保证直接从主存中读取一个变量,如果这个变量被修改后,总是会被写回到主存中去。

针对竞争情况,一个同步块可以保证在同一时刻仅有一个线程可以进入代码的临界区(操作系统概念?)。同步块还可以保证代码块中所有被访问的变量将会从主存中读入,当线程退出同步代码块时,所有被更新的变量都会被刷新回主存中去,不管这个变量是否被声明为 volatile

其他概念:

临界区内的数据一次只能同时被一个进程使用,当一个进程使用临界区内的数据时,其他需要使用临界区数据的进程进入等待状态。

最新文章

  1. 求两点之间最短路径-Dijkstra算法
  2. js 时间构造函数
  3. Linux 信号详解四(pause,alarm)
  4. 如何使用jquery - ui 的图标icons 及图标的相对位置 +jquerui是如何来显示图标的?
  5. backbonejs中的模型篇(三)
  6. 解决phpMyAdmin中缺少mysqli扩展的错误
  7. 【原创】lua的module的一些点
  8. C# & SQLite - Storing Images
  9. JavaScript学习总结(二)
  10. python学习之路-12
  11. 删除 win8.1中的网络1,网络2,宽带连接1,宽带连接2等网络记录
  12. jQuery修炼心得-DOM节点的删除
  13. c++ 智能指针【转载】
  14. 浅析fork()和底层实现
  15. seo相关知识
  16. Windows 8(64位)如何搭建 Android 开发环境与真机测试(转)
  17. Metasploit渗透技巧:后渗透Meterpreter代理
  18. 【MySQL】【3】String和Date相互转换
  19. 代码重定位和位置无关码——运行于nor flash
  20. MyBatis环境配置及入门

热门文章

  1. IDLE经常使用快捷键汇总
  2. WM_MOUSELEAVE 和 WM_MOUSEHOVER 使用
  3. ubuntu的apt-get提示资源被锁定
  4. mysql update常见实例
  5. Oracle学习笔记之七(用户管理、角色与权限、导入导出等)
  6. 微信开发,对象转换为xml时候引用XStream这个类报错处理方案
  7. CCTargetedAction
  8. 李洪强iOS开发之FMDB线程安全的用法
  9. Ng-cloak解决angularJs中的闪烁问题
  10. 【转载】用Pwnage + Redsnow 制作完美越狱固件