网站建设图片大全青岛网站建设策划
2026/6/9 20:37:09 网站建设 项目流程
网站建设图片大全,青岛网站建设策划,西安网站制作多少钱,如何做网站安全扫描JMM核心内容概览与重要程度评级在学习JMM前#xff0c;我们先了解其核心内容体系及重要程度#xff1a;内容模块 重要程度 说明1. JMM基础概念 ⭐⭐⭐⭐ 理解JMM的出发点和基本架构- 硬件基础与并发挑战 ⭐⭐⭐⭐ 了解JMM存在的必要性- 主内存与工作内存 ⭐⭐⭐⭐ JMM的核心抽…JMM核心内容概览与重要程度评级在学习JMM前我们先了解其核心内容体系及重要程度内容模块 重要程度 说明1. JMM基础概念 ⭐⭐⭐⭐ 理解JMM的出发点和基本架构- 硬件基础与并发挑战 ⭐⭐⭐⭐ 了解JMM存在的必要性- 主内存与工作内存 ⭐⭐⭐⭐ JMM的核心抽象概念2. 内存间交互操作 ⭐⭐⭐ JMM的基础操作定义3. volatile关键字 ⭐⭐⭐⭐⭐ 最常用的同步机制必须深入掌握4. synchronized内存语义 ⭐⭐⭐⭐⭐ 理解锁的内存效应5. happens-before规则 ⭐⭐⭐⭐⭐ JMM的理论核心解决可见性问题的关键6. 原子性、可见性、有序性 ⭐⭐⭐⭐⭐ 并发编程的三大核心问题7. 安全发布模式 ⭐⭐⭐⭐ 实际开发中的常用技巧8. final字段语义 ⭐⭐⭐ 特殊但重要的内存语义9. 双重检查锁定问题 ⭐⭐⭐⭐ 经典问题的分析与解决方案10. JMM底层实现 ⭐⭐⭐ 理解原理优化性能接下来我们将按照重要程度逐一深入讲解各个模块。1. JMM是什么为什么需要JMM1.1 JMM的定义与作用Java内存模型Java Memory Model, JMM 是Java虚拟机规范中定义的一种抽象规范用于屏蔽各种硬件和操作系统的内存访问差异实现Java程序在各种平台下都能达到一致的内存访问效果。JMM的核心作用定义规则规定多线程环境下变量的访问方式提供保证确保在不同平台上内存访问行为的一致性允许优化在保证正确性的前提下允许编译器和处理器进行优化1.2 为什么需要JMM硬件层面的挑战现代计算机系统的多层次存储架构导致了并发编程的三大核心问题public class ConcurrencyProblems {private static boolean ready false;private static int number 0;public static void main(String[] args) {// 线程1数据准备Thread writer new Thread(() - {number 42; // 操作1可能被重排序到操作2之后ready true; // 操作2可能先执行});// 线程2数据处理Thread reader new Thread(() - {while (!ready) {// 等待ready变为trueThread.yield();}// 可能输出0而不是42System.out.println(Number: number);});writer.start();reader.start();}}问题根源CPU缓存一致性多核CPU各有缓存数据更新不同步指令重排序编译器和处理器为优化性能重新排序指令内存可见性一个线程的修改对其他线程不可见2. JMM的核心架构主内存与工作内存JMM通过抽象的内存模型解决上述问题物理硬件对应关系CPU Core 1缓存 L1/L2CPU Core 2缓存 L1/L2共享缓存 L3主内存 RAMJMM内存模型线程2线程1read/loadstore/writeread/loadstore/write工作内存主内存变量副本工作内存主内存变量副本执行引擎执行引擎主内存 Main Memory共享变量存储区域工作内存与主内存的交互通过8种原子操作完成public class MemoryOperations {private int sharedValue 0;public void operationExample() {// 1. read: 从主内存读取变量到传输通道// 2. load: 将read得到的值放入工作内存的变量副本// 相当于: int temp sharedValue; (但这是高级语言表示)// 3. use: 将工作内存中的变量传递给执行引擎int result sharedValue * 2;// 4. assign: 将执行引擎的结果赋给工作内存中的变量sharedValue result 1;// 5. store: 将工作内存中的变量值传输到主内存的传输通道// 6. write: 将store获取的值放入主内存的变量// 7. lock: 将主内存变量标记为线程独占状态// 8. unlock: 释放锁定的变量}}3. ⭐⭐⭐⭐⭐ volatile关键字深度解析3.1 volatile的语义与保证volatile是JVM提供的最轻量级的同步机制提供两大保证可见性保证对volatile变量的写操作立即对其他线程可见禁止重排序阻止编译器和处理器对volatile操作进行重排序public class VolatileExample {private volatile boolean flag false;private int value 0;public void writer() {value 42; // 普通写操作// StoreStore内存屏障禁止上面的普通写与下面的volatile写重排序flag true; // volatile写操作// StoreLoad内存屏障确保volatile写立即对其他处理器可见}public void reader() {// LoadLoad内存屏障确保volatile读之前的所有读操作已完成if (flag) { // volatile读操作// LoadStore内存屏障确保volatile读之后的写操作不会重排序到读之前System.out.println(value); // 保证看到value 42}}}3.2 volatile的实现原理在硬件层面volatile通过内存屏障指令实现public class VolatileBarrier {private volatile int value;public void setValue(int newValue) {this.value newValue;// 对应x86汇编代码// mov %eax,0x10(%rsi) ; 将newValue存入value的内存地址// lock addl $0x0,(%rsp) ; StoreLoad内存屏障mfence指令}public int getValue() {// volatile读在x86上不需要特殊指令// 因为x86的内存模型已经保证了可见性TSO模型return value;}}内存屏障类型LoadLoad屏障禁止读操作重排序StoreStore屏障禁止写操作重排序LoadStore屏障禁止读与写操作重排序StoreLoad屏障禁止写与读操作重排序最重量级3.3 volatile的使用场景与限制适用场景状态标志位一次性安全发布独立观察independent observation开销较低的读-写锁策略不适用场景复合操作如i依赖于当前值的操作如value value 1public class VolatileUsage {// 场景1状态标志位private volatile boolean shutdownRequested;public void shutdown() {shutdownRequested true;}public void doWork() {while (!shutdownRequested) {// 执行工作任务}}// 场景2一次性安全发布private volatile Resource resource;public Resource getResource() {if (resource null) {synchronized(this) {if (resource null) {resource new Resource(); // 安全发布}}}return resource;}}4. ⭐⭐⭐⭐⭐ synchronized的内存语义synchronized不仅提供互斥执行还提供重要的内存语义public class SynchronizedMemory {private int counter 0;private final Object lock new Object();public void increment() {synchronized(lock) {// monitorenter指令// 1. 清空工作内存// 2. 从主内存重新加载所有共享变量counter;// 临界区内的操作不会被重排序到临界区外}// monitorexit指令// 1. 将工作内存中的修改刷新到主内存// 2. 释放锁}public int getCounter() {synchronized(lock) {// 获取锁会强制从主内存重新读取变量return counter;}}}synchronized的内存语义进入同步块清空工作内存从主内存重新加载变量退出同步块将工作内存中的修改刷新到主内存互斥执行确保同一时刻只有一个线程执行临界区代码5. ⭐⭐⭐⭐⭐ happens-before规则happens-before是JMM的理论核心定义了操作之间的可见性关系。5.1 happens-before规则详解public class HappensBeforeExample {private int x 0;private volatile boolean v false;private int y 0;private final Object lock new Object();public void demo() {// 规则1程序次序规则x 1; // 操作Av true; // 操作BA happens-before B// 规则2volatile变量规则if (v) { // 操作CB happens-before Cy x; // 操作DC happens-before D}// 规则3传递性规则// A happens-before B, B happens-before C, C happens-before D// 因此 A happens-before D// 规则4管程锁定规则synchronized(lock) { // 加锁Ex 2; // 操作FE happens-before F} // 解锁GF happens-before G// 规则5线程启动规则Thread t new Thread(() - {System.out.println(x); // 看到x2});t.start(); // start() happens-before 线程中的所有操作// 规则6线程终止规则try {t.join(); // 线程中的所有操作 happens-before join()返回} catch (InterruptedException e) {Thread.currentThread().interrupt();}// 规则7对象终结规则// 对象的构造函数执行结束 happens-before finalize()方法开始}}5.2 happens-before的数学基础happens-before关系是一个偏序关系具有自反性A happens-before A反对称性如果A happens-before B且B happens-before A则AB传递性如果A happens-before B且B happens-before C则A happens-before C6. ⭐⭐⭐⭐⭐ 原子性、可见性、有序性这是并发编程的三大核心问题JMM为每个问题提供了解决方案。6.1 原子性Atomicity原子性是指一个操作不可中断要么全部执行成功要么完全不执行。public class AtomicityExample {private int basicType 0; // 基本类型访问是原子的private long longValue 0L; // long和double可能非原子但现代JVM通常保证原子性private volatile boolean flag false; // volatile保证单个读/写的原子性// 复合操作不是原子的public void nonAtomicIncrement() {basicType; // 不是原子操作分解为read-modify-write三步}// 保证原子性的方式private final AtomicInteger atomicInt new AtomicInteger(0);private final Object lock new Object();private int synchronizedValue 0;public void atomicOperations() {// 方式1使用原子类atomicInt.incrementAndGet(); // 原子操作// 方式2使用同步synchronized(lock) {synchronizedValue; // 原子操作}// 方式3使用volatile变量仅适用于特定场景flag true; // 原子操作}}6.2 可见性Visibility可见性是指当一个线程修改了共享变量的值其他线程能够立即得知这个修改。public class VisibilityExample {private int noVisibility 0; // 无可见性保证private volatile boolean hasVisibility false; // volatile保证可见性private int synchronizedValue 0; // synchronized保证可见性private final Object lock new Object();public void demonstrate() {// 线程1修改数据new Thread(() - {noVisibility 42;hasVisibility true;synchronized(lock) {synchronizedValue 100;}}).start();// 线程2读取数据new Thread(() - {// 可能看不到noVisibility的更新while (!hasVisibility) {// 等待hasVisibility变为true}// 保证看到noVisibility 42因为volatile写happens-before volatile读synchronized(lock) {// 保证看到synchronizedValue 100}}).start();}}6.3 有序性Ordering有序性是指程序执行的顺序按照代码的先后顺序执行。public class OrderingExample {private int x 0;private int y 0;private volatile boolean ready false;public void orderingDemo() {// 线程1可能被重排序new Thread(() - {x 1; // 操作1y 2; // 操作2ready true; // 操作3volatile写阻止重排序}).start();// 线程2new Thread(() - {while (!ready) {// 等待}// 由于volatile的语义这里保证看到x1, y2// 不会出现y2但x0的情况}).start();}}7. ⭐⭐⭐⭐ 安全发布模式安全地发布对象是并发编程中的常见需求JMM提供了多种模式。public class SafePublication {// 方式1静态初始化器最安全private static final Resource staticResource new Resource();// 方式2volatile字段private volatile Resource volatileResource;public void initVolatileResource() {volatileResource new Resource(); // 安全发布}// 方式3final字段private final Resource finalResource;public SafePublication() {this.finalResource new Resource(); // 安全发布}// 方式4正常锁保护private Resource guardedResource;private final Object lock new Object();public void initGuardedResource() {synchronized(lock) {if (guardedResource null) {guardedResource new Resource(); // 安全发布}}}// 方式5线程安全容器private final MapString, Resource safeMap Collections.synchronizedMap(new HashMap());private final ConcurrentMapString, Resource concurrentMap new ConcurrentHashMap();public void addToSafeMap(String key) {safeMap.put(key, new Resource()); // 安全发布}}8. ⭐⭐⭐⭐ 双重检查锁定DCL问题与解决方案双重检查锁定是一个经典的并发模式但存在陷阱。8.1 错误的DCL实现public class BrokenDCL {private static Resource resource; // 没有volatile!public static Resource getInstance() {if (resource null) { // 第一次检查无锁synchronized(BrokenDCL.class) { // 加锁if (resource null) { // 第二次检查有锁resource new Resource(); // 问题所在// 可能发生的重排序// 1. 分配内存空间// 2. 将引用指向内存空间此时resource ! null// 3. 初始化对象还未执行// 其他线程可能拿到未完全初始化的对象}}}return resource;}}8.2 正确的DCL实现public class CorrectDCL {// 使用volatile禁止重排序private static volatile CorrectDCL instance;private final int value;private final String name;private CorrectDCL() {this.value 42; // 初始化final字段this.name DCL; // 初始化普通字段// 构造函数执行}public static CorrectDCL getInstance() {if (instance null) { // 第一次检查无锁synchronized(CorrectDCL.class) { // 加锁if (instance null) { // 第二次检查有锁instance new CorrectDCL(); // 安全发布// volatile写插入内存屏障确保// 1. 所有初始化操作完成// 2. 初始化结果对其他线程立即可见}}}return instance;}}9. ⭐⭐⭐ final字段的内存语义final字段在并发编程中有特殊的内存语义提供了安全初始化的保证。public class FinalFieldExample {private final int finalValue; // final字段private int normalValue; // 普通字段private volatile boolean ready false;public FinalFieldExample() {normalValue 1; // 普通字段写入可能被重排序finalValue 42; // final字段写入// JMM在此隐式插入StoreStore内存屏障// 确保final字段的初始化不会被重排序到构造函数之外ready true; // volatile写}public static void reader() {FinalFieldExample obj new FinalFieldExample();// 保证看到finalValue的正确值(42)// 即使没有同步也能看到正确初始化的final字段int r1 obj.finalValue;// 可能看到normalValue的默认值(0)而不是1// 因为没有同步保证int r2 obj.normalValue;// 但如果通过volatile读看到readytrue// 那么也能保证看到所有字段的正确初始化值if (obj.ready) {// 保证看到finalValue42和normalValue1}}}10. JMM在开发中的实际应用10.1 性能优化建议减少同步范围只在必要时使用同步使用volatile代替锁当只需要可见性保证时使用线程局部变量避免共享消除同步使用并发容器代替手动同步的容器10.2 常见陷阱与避免方法public class CommonConcurrencyMistakes {// 陷阱1认为volatile保证原子性private volatile int count 0;public void unsafeIncrement() {count; // 不是原子操作}// 解决方案使用原子类或同步private final AtomicInteger safeCount new AtomicInteger(0);private int synchronizedCount 0;private final Object lock new Object();public void safeIncrement() {safeCount.incrementAndGet(); // 方式1原子类synchronized(lock) { // 方式2同步synchronizedCount;}}// 陷阱2误用双重检查锁定// 解决方案使用volatile修饰实例变量// 陷阱3依赖线程优先级// 解决方案不要依赖线程优先级进行正确性设计// 陷阱4在构造函数中启动线程public class ProblematicConstructor {public ProblematicConstructor() {new Thread(() - {// 可能访问未完全初始化的对象}).start();}}}总结Java内存模型是Java并发编程的基石它通过定义一系列规则和happens-before关系在多线程环境中提供了内存可见性、原子性和有序性的保证。关键要点理解happens-before规则这是理解线程间操作可见性的核心正确使用volatile了解其适用场景和限制掌握安全发布模式确保对象在线程间安全共享避免常见陷阱识别并避免常见的并发编程错误

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询