Java 内存模型

news/2024/10/2 23:10:19

Author: ACatSmiling

Since: 2024-07-24

概念

Java 内存模型Java Memory Model,简称 JMM,是 Java 语言中定义的一组规则和规范,用于解决多线程环境下的内存可见性和有序性问题。JMM 确定了线程之间如何通过内存进行交互,并规定了变量的读取和写入操作的行为。

JMM 能干吗?

  • 通过 JMM 来实现线程的工作内存和主内存之间的抽象关系。
  • 屏蔽各个硬件平台和操作系统的内存访问差异,以实现让 Java 程序在各种平台下都能达到一致性的内存访问效果。

抽象模型

image-20240724224217335

JMM 规定了所有的变量都存储在主内存中,每个线程都有自己的工作内存,线程自己的工作内存中保存了该线程使用到的主内存变量的副本拷贝,线程对变量的所有操作(读取、赋值等)都必须在线程自己的工作内存中进行,而不能够直接写入主内存中的变量,不同线程之间也无法直接访问对方工作内存中的变量,线程间变量值的传递均需要通过主内存来完成。

  • 主内存(Main Memory):所有变量都存储在主内存中,主内存是所有线程共享的区域。
  • 工作内存(Working Memory):每个线程都有自己的工作内存(类似于 CPU 缓存),线程在工作内存中对变量进行操作。工作内存中的变量是主内存中变量的拷贝,线程对变量的修改必须在某个时刻刷新回主内存。

三大特性

内存可见性:JMM 规定了一个线程对共享变量的修改何时对另一个线程可见,在没有适当的同步机制时,线程可能会看到旧的、不一致的数据。

原子性:JMM 确保基本的读写操作是原子的(不可分割的)。

有序性:JMM 规定了程序中指令的执行顺序,编译器和处理器可能会对指令进行重排序,但 JMM 规定了哪些重排序是可见的,哪些是不可见的,以确保某些操作不会被重排序而破坏程序的正确性。

可见性规则

为了确保多线程编程中的可见性和有序性,JMM 定义了一些关键的同步原语和规则:

  1. volatile 变量
    • 对 volatile 变量的读写操作具有可见性和有序性。
    • 当一个线程修改了 volatile 变量,新的值会立即被刷新到主内存中,其他线程读取时会直接从主内存中读取。
  2. synchronized 块
    • synchronized 块可以确保进入同步块的线程对共享变量的修改对其他线程可见。
    • 每个对象都有一个监视器锁(monitor lock),线程通过获取锁来实现同步。
  3. final 变量
    • final 变量在构造函数结束后不能被修改,且在构造函数中对 final 变量的写入对其他线程可见。

happens-before 原则

happens-before 原则happens-before 关系定义了一个操作的结果对另一个操作可见的条件,可以用于确定多个操作之间的顺序性和可见性,进而确保了多线程程序中的内存一致性和正确性。通过遵循这些规则,开发者可以确保在多线程环境中读写共享变量时不会出现意外的行为。

happens-before 原则内容如下:

  1. 程序次序规则(Program Order Rule)在一个线程内,按照程序的顺序,前面的操作 happens-before 后面的操作。例如,在同一个线程中,a = 1; b = 2;,则 a = 1 happens-before b = 2。
  2. 监视器锁规则(Monitor Lock Rule)对一个锁的解锁操作 happens-before 其后的对这个锁的加锁操作。例如,线程 A 对某个对象的解锁操作 happens-before 线程 B 对同一个对象的加锁操作。
  3. volatile 变量规则(Volatile Variable Rule)对一个 volatile 变量的写操作 happens-before 后续对这个 volatile 变量的读操作。例如,线程 A 对 volatile 变量 x 的写操作 x = 1 happens-before 线程 B 对 x 的读操作 int y = x。
  4. 线程启动规则(Thread Start Rule)在主线程中对线程对象的启动操作 happens-before 启动线程中的每一个操作。例如,主线程调用 thread.start() happens-before 新线程中的任何操作。
  5. 线程中断规则(Thread Interruption Rule)对线程对象的中断操作 happens-before 被中断线程检测到中断事件的发生。例如,主线程调用 thread.interrupt() happens-before 被中断线程检测到中断(通过 Thread.interrupted() 或 Thread.isInterrupted())。
  6. 线程终止规则(Thread Termination Rule)一个线程中的所有操作 happens-before 另一个线程检测到这个线程已经终止或等待这个线程终止。例如,线程 A 中的所有操作 happens-before 主线程检测到线程 A 已终止(通过 thread.join())。
  7. 对象构造规则(Object Construction Rule)对象的构造函数的执行 happens-before 该对象的 finalize() 方法的开始。例如,某个对象的构造函数执行完毕 happens-before 该对象的 finalize() 方法开始。
  8. 传递性(Transitivity)如果 A happens-before B,且 B happens-before C,那么 A happens-before C。例如,如果 a = 1 happens-before b = 2,且 b = 2 happens-before c = 3,那么 a = 1 happens-before c = 3。

原文链接

https://github.com/ACatSmiling/zero-to-zero/blob/main/JavaLanguage/java-util-concurrent.md

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.ryyt.cn/news/67235.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈,一经查实,立即删除!

相关文章

《Java 高级篇》八:新特性

Java 中的一些新特性:Lambda 表达式、函数式接口、Stream API。Author: ACatSmiling Since: 2024-10-01Lambda 表达式 Lambda 是一个匿名函数,我们可以把 Lambda 表达式理解为是一段可以传递的代码(将代码像数据一样进行传递)。使用它可以写出更简洁、更灵活的代码。作为一…

高级语言程序设计第二次作业

这个作业属于哪个课程 2024高级语言程序设计 (福州大学 - 计算机与大数据学院)这个作业要求在哪里 高级语言程序设计课程第二次个人作业学号 052205124姓名 林宇作业内容: 1.编写并运行书本第3章3.11 编程练习题目中的第1题~第8题 (1):通过试验(即编写带有此类问题的程序)…

《Java 高级篇》六:I/O 流

Java 中的文件系统和 I/O 流。Author: ACatSmiling Since: 2024-10-01字符编码 字符集 Charset:也叫编码表。是一个系统支持的所有字符的集合,包括各国家文字、标点符号、图形符号、数字等。编码表的由来:计算机只能识别二进制数据,早期由来是电信号。为了方便应用计算机,…

《Java 高级篇》七:线程和线程池

Java 中线程的创建方式,以及线程池的应用。Author: ACatSmiling Since: 2024-10-01程序、进程和线程 程序(program):是为完成特定任务、用某种语言编写的一组指令的集合。即指一段静态的代码,静态对象。 进程(process):是程序的一次执行过程,或是正在运行的一个程序。…

《Java 高级篇》五:数据结构

Java 中的数组和集合,ArrayList、HashMap 的源码和底层数据结构分析。Author: ACatSmiling Since: 2024-10-01概述 在 Java 语言中,数组(Array)和集合都是对多个数据进行存储操作的结构,简称Java 容器。此时的存储,主要指的是内存层面的存储,不涉及到持久化的存储。 数组…

06-论说文:审题与立意(3)

06-论说文:审题与立意(3) 立意 就提论题 不能写创新 违反同一律 手段 目的 多谈主张 立意过宽 立意过窄 多谈主张 手段+目的 要结合题干信息 假大空 大而不当 审题立意是整体性的

linux系统配置及相关文件

一.本地服务器:几个相关软件 123432 (一)vmware <关键字:虚拟机(搭建虚拟环境) (二)MobaXterm 关键字:连接 (三) 1231314参考链接 1231314