java内存模型介绍[通俗易懂]

java内存模型介绍[通俗易懂]####Java内存模型Java内存模型描述了Java虚拟机和计算机内存之间是如何协同工作的。一个Java虚拟机也是一个完整的计算机的模型,因此,这个模型自然也包含了内存模型。如果你想写出表现良好的并发程序就必须理解Java内存模型。Java内存模型描述了不同线程间如何和何时看到被其他线程修改的共享变量以及在需要时如何同步访问共享变量。原来的Java内存模型存在很多不足,所以在Java5时进行了修改。这个一直使用至今。####Java内存模型每个运行在Java虚拟机中的线程都拥有自己的线程栈。这

大家好,又见面了,我是你们的朋友全栈君。

####Java内存模型
Java内存模型描述了Java虚拟机和计算机内存之间是如何协同工作的。一个Java虚拟机也是一个完整的计算机的模型,因此,这个模型自然也包含了内存模型。

如果你想写出表现良好的并发程序就必须理解Java内存模型。Java内存模型描述了不同线程间如何和何时看到被其他线程修改的共享变量以及在需要时如何同步访问共享变量。

原来的Java内存模型存在很多不足,所以在Java5时进行了修改。这个一直使用至今。

####Java内存模型

Java_Memory_Model

每个运行在Java虚拟机中的线程都拥有自己的线程栈。这个线程栈包含了这个线程所调用方法的当前执行点,所有我们也可以称之为”调用栈“。在线程执行代码的过程总,调用栈随之发生变化。

线程栈也包含每个被执行的方法中的所有局部变量。一个线程只能访问自己的线程栈。一个线程创建的局部变量对其他线程是不可见的。即使两个线程执行同样的代码,这两个线程任然需要在它们各自的线程栈中创建这些变量。

所有的基本类型的局部变量都全部存放在各自的线程栈中,对其他线程不可见。一个线程可能会向另一个线程传递一个基本类型变量的拷贝,但是这并不能共享基本类型变量自身。

在堆中包含所有你在Java程序中创建的对象。这也包含所有基本类型所对应的装箱类型。即便,我们创建了一个对象然后我们把它赋给了一个局部变量,或者作为另一个对象的成员变量,这个对象仍然存放在堆中。

Java_Memory_Model

一个局部变量可能是基本类型,这样它就永远呆在线程栈中。

一个局部变量也可能是引用变量。在这种情况下,引用变量存放在线程栈中,对象本身存放在堆中。

一个对象可能包含方法,这些方法又可能包含局部变量。这些局部变量也被存放在线程栈中,即便这个方法所属的对象存放在堆中。

一个对象的成员变量随着对象自身存放在堆中。不管这个变量是基本类型还是引用类型都是如此。

静态类变量随着类定义也存放在堆中。

存放在堆中的对象可以被所有的线程通过指向对象的引用访问。当一个线程访问一个对象时,它也可以访问这个对象的成员遍历。如果两个线程在同一时刻调用同一个对象上的同一个方法,它们都可以访问对象的成员变量,但是每个线程都会拥有各自的局部变量拷贝。

Java_Memory_Model

####硬件内存架构
现代硬件内存架构和Java内存模型有一些不一样的地方。理解硬件内存架构和Java内存模型如何和它协同工作也非常重要。
通用的硬件内存架构:

hardware_memory_arch

现代计算机通常拥有两个或多个CPU。这些CPU中可能还有是多核的。这一点,使得多个线程同时运行在一台计算机上称为了可能。每个CPU可以在任何时刻运行一个线程。
这就意味着如果你的程序是多线程的,在你的程序内部,一个线程对应一个CPU可能同时运行。

每个CPU包含一些寄存器。CPU可以在这些寄存器上执行操作会比在内存上快很多。这是因为CPU访问寄存器的速度远高于访问内存的速度。

每个CPU还可能拥有一个CPU缓存层。实际上,现代计算机都会有一个一定大小的缓存层。CPU访问缓存的速度远高于主存,但通常又低于访问寄存器的速度。因此,缓存是用来平衡CPU访问寄存器和主存之间的速度差异的。一些CPU可能拥有多级缓存(一级缓存和二级缓存)。

一台计算机还拥有一块主存区域(RAM)。所有的CPU都可以访问主存。主存区域通常要比CPU的缓存大得多。

通常,当一个CPU需要访问主存的时候,它会将数据从主存读到CPU的缓存中,甚至再从CPU的缓存读到它内部的寄存器中,然后执行相关的操作。当CPU需要将结果写回到主存中时,它会先将值刷新到缓存中,然后在某一时刻刷新回主存中。

当CPU需要在缓存中存储一些其他的东西时,会将存储在缓存中的值刷新回主存中。

CPU缓存可以局部刷新。

####Java内存模型和硬件内存架构之间的联接

正如上面所提到的,Java内存模型和硬件内存架构是不同。在硬件内存架构并不区分内存栈和堆。在硬件中,所有的线程栈和堆都位于主存中。线程栈的一部分和堆可能同一位于CPU缓存和寄存器中。

gap

当对象和变量存放在计算机的不同内存区域中时,就会暴露出一些问题。主要包括两个方面:

  • 内存可见性
  • 当读,检查和写共享变量时的竞争条件

#####内存可见性
如果两个或多个线程共享同一个对象时,在不使用vloatile声明或者同步的情况下,一个线程更新了这个共享对象的值可能对其他线程不可见。

想象一下,这个共享对象最初存放在主存中。运行在一个CPU上的一个线程,将这个共享对象读到它的CPU缓存中。并在缓存中修改了这个共享对象。只要这个CPU缓存还没有刷新回主存,这个共享共享对象变化后的版本对其它CPU的线程来说就是不可见的。这种方式可能使每个线程最终拥有这个共享对象的拷贝,每个拷贝都停留在不同的CPU缓存中。

cache

解决这个问题,可以使用Java中的volatile关键字。volatile关键字可以确保你直接从主存中读取一个给定的变量,当变量发生更新总是会被写回到主存中。

#####竞争条件
如果两个或者多个线程共享一个对象,超过一个对象去更新对象上的变量,竞争条件可能就会发生。

race_condition

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/157183.html原文链接:https://javaforall.net

(0)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • 分享6个免费的优质动漫网站

    分享6个免费的优质动漫网站我们在闲暇之余,可能会看看动漫来打发一下我们无聊的时光,但我们可以看动漫的地方少之又少,很多的动漫要看的话需要充VIP的,就算充了钱,还是有许多的动漫我们是没法看的,今天给大家带来6个免费的动漫网站,大家一起来看看吧。1.樱花动漫这个网站的动漫资源都是免费的,不管是国产动漫,还是外国动漫,在这个网站里面都有,这个网站特别适合看日漫。如果你去这个网站看动漫的话能让你看个够。2.哔哩哔哩这…

    2022年6月15日
    183
  • Dubbo入门_dubbo的原理

    Dubbo入门_dubbo的原理dubbo分布式系统简介发展演变RPCdubbo核心概念搭建dubbo分布式系统简介“分布式系统是若干独立计算机的集合,这些计算机对于用户来说就像单个相关系统”分布式系统(distributed system)是建立在网络之上的软件系统。随着互联网的发展,网站应用的规模不断扩大,常规的垂直应用架构已无法应对,分布式服务架构以及流动计算架构势在必行,亟需一个治理系统确保架构有条不紊的演进。发展演变单一应用架构当网站流量很小时,只需一个应用,将所有功能都部署在一起,以减少部署节点和成本。此时

    2022年8月8日
    3
  • GCC、ARM-LINUX-GCC、ARM-ELF-GCC浅析

    一、GCC简介:TheGNUCompilerCollection,通常简称GCC,是一套由GNU开发的编译器集,为什么是编辑器集而不是编译器呢?那是因为它不仅支持C语言编译,还支持C++,A

    2021年12月27日
    49
  • plot绘图颜色_matlab画图plot详细

    plot绘图颜色_matlab画图plot详细所有颜色的名字及值:’aliceblue’:’#F0F8FF’,’antiquewhite’:’#FAEBD7′,’aqua’:’#00FFFF’,’aquamarine’:’#7FFFD4′,’azure’:’#F0FFFF’,’beige’:’#F5F5DC’,’bisque’:’#FFE4C4′,

    2022年10月15日
    0
  • python3.8安装scrapy_安装scrapy

    python3.8安装scrapy_安装scrapy抓取网站的代码实现很多,如果考虑到抓取下载大量内容,scrapy框架无疑是一个很好的工具。下面简单列出安装过程。PS:一定要按照Python的版本下载,要不然安装的时候会提醒找不到Python。1.安装Python安装完了记得配置环境,将python目录和python目录下的Scripts目录添加到系统环境变量的Path里(在python2.7以后版本中,安装过程中会有个选项:添加到python…

    2022年9月17日
    0
  • jvm terminated. exit code -1

    jvm terminated. exit code -1

    2021年5月11日
    147

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号