本节内容是从操作系统的层面谈并发,本节课程我们需要掌握如下内容:
定义: Java 内存模型(即 Java Memory Model,简称 JMM)本身是一种抽象的概念,并不真实存在,它描述的是一组规则或规范,通过这组规范定义了程序中各个变量(包括实例字段,静态字段和构成数组对象的元素)的访问方式。
首先看下图,图中展示了Java 的内存模型。
工作内存(私有):由于JVM 运行程序的实体是线程,而每个线程创建时 JVM 都会为其创建一个工作内存(栈空间),用于存储线程私有的数据。线程私有的数据只能供自己使用,其他线程不能够访问到当前线程私有的内存空间,保证了不同的线程在处理自己的数据时,不受其他线程的影响。
主内存(共享):Java 内存模型中规定所有变量都存储在主内存,主内存是共享内存区域,所有线程都可以访问。从上图中可以看到,Java 的并发内存模型与操作系统的 CPU 运行方式极其相似,这就是 Java 的并发编程模型。通过创建多条线程,并发的进行操作,充分利用系统资源,达到高效的并发运算。
我们知道,线程的私有空间中存储的数据,仅供当前线程自己使用,其他线程不能够对数据进行访问。线程的私有空间会存放很多程序运行时所必须的数据,如:
程序计数器:记录当前方法执行到了哪里,以便 CPU 切换回来之后能够继续执行上次执行到的位置,而不会进行重复执行或者遗漏。
局部变量:局部变量是方法中的变量,只供当前方法使用。
方法参数:Java 方法会定义自己的入参,入参的真实值也会记录到内存空间供当前线程使用。
由于线程的内存空间会存放很多数据,这里只提以上三中数据以供同学理解线程私有空间的意义。
为了加深理解,我们一起看一个简单的代码示例并进行分析:
public class DemoTest{
public static void main(String[] args) {
sum(10); // 解析点 3
}
public static void sum(int num) {
int i = 5; // 解析点 1
set(); //解析点 2
System.out.println("num+i = "+ (num + i));
}
public static void set() {
int i = 100;
}
}
在给出结果之前,我们来分析下:
解析点 1 :设置 i 的值为 5;
解析点 2: 调用 set() 方法,逻辑如下。
public static void set() {
int i = 100;
}
那最终的结果是多少呢?
解析点 3:我们传入的 sum 的参数值是 10,如果想确定结果,只要确定另外一个加数 i 的值就行了。我们通过分析,在方法 sum(int num) 中的 int i = 5 与方法 set() 中的 int i = 100 是两个不同的方法的局部变量,属于线程私有的。互相不会影响,所以set() 方法中的 int i = 100 不会影响最终的结果:
num+i = 15
每个事物都有其生命周期,也就是事物从出生开始到最终消亡这中间的整个过程。在其整个生命周期的历程中,会有不同阶段,每个阶段对应着一种状态,比如:人的一生会经历从婴幼儿、青少年、青壮年、中老年到最终死亡,离开这人世间,这是人一生的状态。
同样的,线程作为一种事物,也有生命周期,在其生命周期中也存在着不同的状态,不同的状态之间还会有互相转换。
Java 线程的声明周期会经历 6 中不同的状态变化,后续章节会有详细描述。从线程的创建到线程执行任务的完成,即 Java 线程的生命周期。
Java 并发理论基础是基于Java 的内存模型的,了解 Java 内存模型,能够更有助于后续对并发知识的理解和运用了。Java 的内存模型是并发原理的基础,在了解内存模型的基础上去理解共享内存和私有内存,了解不同内存状态以及 Java 线程的生命周期至关重要。
0/1000