JVM内存模型(JMM)是什么?如何理解happens-before关系?
困难JVM内存模型
💬0
🔥0
👍0
详细说明JVM内存模型的概念,包括内存可见性、原子性、有序性,以及happens-before关系
参考答案
JVM内存模型(Java Memory Model)定义了Java程序中多线程访问共享内存的规则:
- JMM基本概念
目的
- 屏蔽不同硬件和操作系统的内存访问差异
- 让Java程序在各种平台上都能达到一致的内存访问效果
- 保证多线程程序的正确性
核心问题
- 内存可见性:一个线程对共享变量的修改,其他线程能否立即看到
- 原子性:一个操作是否不可中断
- 有序性:程序执行的顺序是否与代码顺序一致
- 主内存和工作内存
主内存(Main Memory)
- 所有线程共享的内存区域
- 存储所有变量的主本
- 类似于物理机的RAM
工作内存(Working Memory)
- 每个线程独有内存区域
- 存储线程使用变量的副本
- 类似于CPU的缓存
交互规则
- 线程只能操作工作内存中的变量
- 变量值在工作内存和主内存之间传递
- 传递过程需要遵循特定规则
- 内存可见性问题
问题描述
public class VisibilityExample {
private boolean flag = false;
public void setFlag() {
flag = true; // 线程A执行
}
public boolean getFlag() {
return flag; // 线程B执行
}
}
问题分析
- 线程A修改flag后,线程B可能看不到最新值
- 原因:工作内存和主内存不同步
- 结果:程序行为不可预测
解决方案
- 使用volatile关键字
- 使用synchronized关键字
- 使用Lock接口
- 使用Atomic类
- happens-before关系
定义
- 如果操作A happens-before操作B,那么A的结果对B可见
- 是JMM的核心概念
- 用于判断操作的可见性
规则
- 程序顺序规则:同一线程中的操作按程序顺序执行
- 监视器锁规则:解锁操作happens-before后续的加锁操作
- volatile变量规则:写操作happens-before后续的读操作
- 线程启动规则:start()方法happens-before线程中的任何操作
- 线程终止规则:线程中的任何操作happens-before线程终止
- 中断规则:对线程interrupt()的调用happens-before被中断线程的代码检测到中断
- 终结器规则:对象的构造函数happens-before对象的finalize()方法
- 传递性:如果A happens-before B,B happens-before C,那么A happens-before C
- volatile关键字
作用
- 保证变量的可见性
- 禁止指令重排序
- 不保证原子性
实现原理
- 内存屏障:在读写操作前后插入内存屏障
- 禁止重排序:编译器不会重排序volatile操作
- 立即刷新:写操作后立即刷新到主内存
使用场景
public class VolatileExample {
private volatile boolean flag = false;
public void setFlag() {
flag = true; // 立即对其他线程可见
}
public boolean getFlag() {
return flag; // 总是读取最新值
}
}
- synchronized关键字
作用
- 保证原子性:同一时刻只有一个线程执行
- 保证可见性:解锁前将变量刷新到主内存
- 保证有序性:禁止指令重排序
实现原理
- 对象头:Mark Word存储锁信息
- 监视器:每个对象关联一个监视器
- 锁升级:偏向锁→轻量级锁→重量级锁
使用示例
public class SynchronizedExample {
private int count = 0;
public synchronized void increment() {
count++; // 原子操作
}
public synchronized int getCount() {
return count; // 可见性保证
}
}
评论区 (0)
暂无评论,来发表第一条评论吧!