Java 线程内存模型
1. 前言
本节内容是从操作系统的层面谈并发,本节课程我们需要掌握如下内容:
- 了解 Java 的内存模型定义,是 Java 并发编程基本原理的基础知识;
- 从概念上了解线程的私有内存空间和主内存,能够从全局上了解线程是如何进行内存数据的存取操作的;
- 了解线程拥有私有空间的意义,私有空间能够为线程提供独有的数据,其他线程不可干扰;
- 在多线程环境下,主内存操作共享变量需要注意的事项需谨记,数据安全问题很重要;
- Java 线程也是拥有生命周期的,了解它的生命周期,从宏观上了解线程。
2. 什么是 Java 的内存模型
定义: Java 内存模型(即 Java Memory Model,简称 JMM)本身是一种抽象的概念,并不真实存在,它描述的是一组规则或规范,通过这组规范定义了程序中各个变量(包括实例字段,静态字段和构成数组对象的元素)的访问方式。
3. Java 线程的私有内存和主内存
首先看下图,图中展示了Java 的内存模型。
工作内存(私有):由于JVM 运行程序的实体是线程,而每个线程创建时 JVM 都会为其创建一个工作内存(栈空间),用于存储线程私有的数据。线程私有的数据只能供自己使用,其他线程不能够访问到当前线程私有的内存空间,保证了不同的线程在处理自己的数据时,不受其他线程的影响。
主内存(共享):Java 内存模型中规定所有变量都存储在主内存,主内存是共享内存区域,所有线程都可以访问。从上图中可以看到,Java 的并发内存模型与操作系统的 CPU 运行方式极其相似,这就是 Java 的并发编程模型。通过创建多条线程,并发的进行操作,充分利用系统资源,达到高效的并发运算。
4. 线程拥有私有空间的意义
我们知道,线程的私有空间中存储的数据,仅供当前线程自己使用,其他线程不能够对数据进行访问。线程的私有空间会存放很多程序运行时所必须的数据,如:
程序计数器:记录当前方法执行到了哪里,以便 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
5. 主内存操作共享变量需要注意的事项
- 确定是否是多线程环境:多线程环境下操作共享变量需要考虑线程的安全性;
- 确定是否有增删改操作:多线程环境下,如果对共享数据有增加,删除或者修改的操作,需要谨慎。为了保证线程的同步性,必须对该共享数据进行加锁操作,保证多线程环境下,所有的线程能够获取到正确的数据。如生产者与消费者模型,售票模型。这些会在后续章节进行代码实战演练;
- 多线程下的读操作:如果是只读操作,对共享数据不需要进行锁操作,因为数据本身未发生增删改操作,不会影响获取数据的准确性。
6. Java 线程的生命周期
每个事物都有其生命周期,也就是事物从出生开始到最终消亡这中间的整个过程。在其整个生命周期的历程中,会有不同阶段,每个阶段对应着一种状态,比如:人的一生会经历从婴幼儿、青少年、青壮年、中老年到最终死亡,离开这人世间,这是人一生的状态。
同样的,线程作为一种事物,也有生命周期,在其生命周期中也存在着不同的状态,不同的状态之间还会有互相转换。
Java 线程的声明周期会经历 6 中不同的状态变化,后续章节会有详细描述。从线程的创建到线程执行任务的完成,即 Java 线程的生命周期。
7. 小结
Java 并发理论基础是基于Java 的内存模型的,了解 Java 内存模型,能够更有助于后续对并发知识的理解和运用了。Java 的内存模型是并发原理的基础,在了解内存模型的基础上去理解共享内存和私有内存,了解不同内存状态以及 Java 线程的生命周期至关重要。
- 还没有人评论,欢迎说说您的想法!