华为面试官问我关于“多线程之内存模型”,看完这篇,自信满满!

在这里插入图片描述

多线程之内存模型

首先看一下整体概览图

image

我们常说的JVM内存模式指的是JVM的内存分区;而Java内存模式是一种虚拟机规范。Java虚拟机规范中定义了Java内存模型(Java Memory Model,JMM),用于屏蔽掉各种硬件和操作系统的内存访问差异(不同操作系统对缓存一致性的实现有所不同),为了实现让Java程序在各种平台下都能达到一致的并发效果,JMM规范了Java虚拟机与计算机内存是如何协同工作的:规定了一个线程何时可以看到由其他线程修改过后的共享变量的值以及如何同步访问共享变量。

线程同步:从百度百科上查询到的资料:即当有一个线程在对内存进行操作时,其他线程都不可以对这个内存地址进行操作,直到该线程完成操作, 其他线程才能对该内存地址进行操作,而其他线程又处于等待状态。

Java内存模型(不仅仅是JVM内存分区):调用栈和本地变量存放在线程栈上,对象存放在堆上。

先看下在一个JVM进程中的线程栈的分布:

image

再看一下操作系统CPU和内存之间的关系:

image

CPU在操作内存的时候并不是直接进行操作的。而是从CPU到CPU的三级缓存然后再到主存中。JVM运行的时候会将数据放入到主内中。

所以操作系统在执行的时候,会加载JVM运行的数据来将数据取出来来进行实现。

  • 一个本地变量可能是基本类型,在这种情况下,它总是“呆在”线程栈上。
  • 一个本地变量也可能是指向一个对象的一个引用。在这种情况下,引用(这个本地变量)存放在线程栈上,但是对象本身存放在堆上。
  • 一个对象可能包含方法,这些方法可能包含本地变量。这些本地变量仍然存放在线程栈上,即使这些方法所属的对象存放在堆上。
  • 一个对象的成员变量可能随着这个对象自身存放在堆上。不管这个成员变量是原始类型还是引用类型。
  • 静态成员变量跟随着类定义一起也存放在堆上。
  • 存放在堆上的对象可以被所有持有对这个对象引用的线程访问。当一个线程可以访问一个对象时,它也可以访问这个对象的成员变量。如果两个线程同时调用同一个对象上的同一个方法,它们将会都访问这个对象的成员变量,但是每一个线程都拥有这个成员变量的私有拷贝。

对于最后一个情况的就是用lock锁来解释是最恰当的,因为使用了volitile关键字来修饰的,对所有线程来说,都是可见的。

其实对于不加volitile关键字的变量来说,在进行改变之后,其实也是可以发生改变的,但是是否是及时的修改并不一定,所以这就造成可能出现问题。而我们来进行写程序就是为了避免这些可能出现问题的地方。

硬件内存架构

现代硬件内存模型与Java内存模型有一些不同,理解内存模型架构以及Java内存模型如何与它协同工作也是非常重要的。

现代计算机硬件架构的简单图示:

image

  • 多CPU:一个现代计算机通常由两个或者多个CPU。其中一些CPU还有多核。从这一点可以看出,在一个有两个或者多个CPU的现代计算机上同时运行多个线程是可能的。每个CPU在某一时刻运行一个线程是没有问题的。这意味着,如果你的Java程序是多线程的,在你的Java程序中每个CPU上一个线程可能同时(并发)执行。
  • CPU寄存器:每个CPU都包含一系列的寄存器,它们是CPU操作内存的基础。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值