了解Java内存模型(Java Memory Model, JMM)

了解Java内存模型(Java Memory Model, JMM)

Java内存模型(Java Memory Model, JMM)是Java语言规范中规定的一组规则,定义了多线程程序中变量(包括实例字段、静态字段和数组元素)的访问方式。JMM的设计目标是保证线程之间的内存可见性和操作的有序性,从而帮助开发者编写并发安全的程序。本文将详细介绍Java内存模型的各个方面。

1. 内存模型的基础

JMM定义了线程和主内存之间的抽象关系。在JMM中,每个线程都有一个私有的本地内存,包含了该线程使用到的变量的副本。线程之间的通信(例如一个线程写入一个变量,另一个线程读取这个变量)必须通过主内存来完成。一个线程对变量的修改必须在写入主内存后,其他线程才能看到这次修改。

2. 内存可见性

内存可见性是指一个线程对变量的修改,另一个线程能够看到的条件。JMM通过以下几个关键字来保证内存可见性:

2.1 volatile关键字

volatile关键字保证了变量在多个线程之间的可见性。当一个变量被声明为volatile时,JMM会保证所有线程都能看到这个变量的最新值。具体来说,JMM通过以下两个规则实现volatile的语义:

  • 当写入一个volatile变量时,JMM会强制将该变量的值刷新到主内存中。
  • 当读取一个volatile变量时,JMM会强制从主内存中读取该变量的最新值。

2.2 synchronized关键字

synchronized关键字用于实现线程之间的互斥访问。除了互斥功能外,synchronized还可以保证内存可见性:

  • 当一个线程进入synchronized块时,它必须先获得该块对象的锁,并清空本地内存中的变量副本。
  • 当一个线程退出synchronized块时,它必须将对变量的修改刷新到主内存中,并释放锁。

通过这种机制,synchronized保证了在synchronized块内对变量的修改对其他线程可见。

3. 有序性

有序性是指在多线程程序中,程序的执行顺序与代码的顺序一致。JMM通过以下几个方面来保证有序性:

3.1 happens-before规则

JMM通过happens-before原则来定义操作之间的有序性。happens-before是指如果一个操作happens-before另一个操作,那么第一个操作的结果对第二个操作可见,并且第一个操作在第二个操作之前执行。JMM定义了以下几种常见的happens-before关系:

  • 程序次序规则:在一个线程内,按照代码顺序,前面的操作happens-before后面的操作。
  • 锁定规则:一个unlock操作happens-before后面对同一个锁的lock操作。
  • volatile变量规则:对一个volatile变量的写操作happens-before后面对该变量的读操作。
  • 线程启动规则:Thread对象的start()方法happens-before该线程的每一个动作。
  • 线程终止规则:线程中的所有操作happens-before其他线程检测到该线程已经终止(通过Thread.join()或Thread.isAlive()方法)。

3.2 指令重排序

为了提高性能,编译器和处理器可能会对指令进行重排序,但这种重排序不会违反happens-before规则。JMM通过内存屏障(Memory Barriers)来禁止特定的重排序,从而保证程序的有序性和正确性。

4. 常见的内存一致性错误

在多线程编程中,未能正确处理内存可见性和有序性可能会导致一些常见的内存一致性错误,例如:

  • 读脏数据:一个线程读取了另一个线程未同步的写入数据。
  • 重排序导致的数据丢失:指令重排序导致程序的执行结果与预期不一致。

为了避免这些问题,开发者应当遵循JMM规定的规则,正确使用volatile和synchronized等关键字。

参考链接

  1. Java内存模型(JMM)详解:https://docs.oracle.com/javase/specs/jls/se11/html/jls-17.html
  2. Java并发编程实践(Java Concurrency in Practice):https://jcip.net/
相关推荐
一只自律的鸡21 分钟前
C项目 天天酷跑(下篇)
c语言·开发语言
计算机徐师兄23 分钟前
Java基于SSM框架的无中介租房系统小程序【附源码、文档】
java·微信小程序·小程序·无中介租房系统小程序·java无中介租房系统小程序·无中介租房微信小程序
源码哥_博纳软云24 分钟前
JAVA智慧养老养老护理帮忙代办陪诊陪护小程序APP源码
java·开发语言·微信小程序·小程序·微信公众平台
沐泽Mu27 分钟前
嵌入式学习-QT-Day05
开发语言·c++·qt·学习
东阳马生架构28 分钟前
JVM实战—2.JVM内存设置与对象分配流转
jvm
小板凳-BGM38 分钟前
C# 第二阶段 modbus
开发语言·ui·c#
问道飞鱼40 分钟前
【Python知识】Python进阶-什么是装饰器?
开发语言·python·装饰器
长安——归故李43 分钟前
【C语言】成绩等级制
c语言·开发语言
黄金小码农1 小时前
c# 2024/12/25 周三
开发语言·c#
忒可君1 小时前
C# winform 报错:类型“System.Int32”的对象无法转换为类型“System.Int16”。
java·开发语言