java内存模型

Java内存模型(Java Memory Model, JMM)是Java虚拟机(JVM)规范中定义的一种抽象模型,用于描述多线程环境下,线程如何与主内存和工作内存交互,以及如何保证线程之间的可见性、有序性和原子性。JMM是理解Java并发编程的基础,尤其是在多线程环境下,如何正确同步共享数据。


1. Java内存模型的核心概念

(1)主内存(Main Memory)
  • 主内存是所有线程共享的内存区域,存储了所有的变量(实例字段、静态字段等)。

  • 主内存是JVM堆内存的一部分。

(2)工作内存(Working Memory)
  • 每个线程都有自己的工作内存,存储了该线程使用的变量的副本。

  • 工作内存是线程私有的,可能是CPU缓存或寄存器。

(3)内存交互操作

JMM定义了以下8种操作来实现主内存和工作内存之间的交互:

  1. lock(锁定):作用于主内存变量,标识变量为线程独占状态。

  2. unlock(解锁):作用于主内存变量,释放锁定状态。

  3. read(读取):从主内存读取变量到工作内存。

  4. load(加载):将read操作读取的值放入工作内存的变量副本中。

  5. use(使用):将工作内存中的变量值传递给执行引擎(如CPU)。

  6. assign(赋值):将执行引擎计算的结果赋值给工作内存中的变量。

  7. store(存储):将工作内存中的变量值传送到主内存。

  8. write(写入):将store操作传送的值写入主内存的变量中。


2. Java内存模型的三大特性

(1)原子性(Atomicity)
  • 原子性是指一个操作是不可分割的,要么全部执行成功,要么全部不执行。

  • JMM保证对基本数据类型的读写操作是原子的(如intboolean等)。

  • 对于longdouble类型,在32位JVM上可能不是原子的,需要使用volatile关键字保证原子性。

(2)可见性(Visibility)
  • 可见性是指一个线程对共享变量的修改,能够及时被其他线程看到。

  • JMM通过以下机制保证可见性:

    • volatile关键字:确保变量的修改对所有线程立即可见。

    • synchronized关键字:在释放锁之前,会将工作内存中的变量刷新到主内存。

    • final关键字:确保变量在构造完成后对其他线程可见。

(3)有序性(Ordering)
  • 有序性是指程序执行的顺序按照代码的先后顺序执行。

  • JMM通过以下机制保证有序性:

    • volatile关键字:禁止指令重排序。

    • synchronized关键字:确保同一时刻只有一个线程执行同步代码块。

    • happens-before原则:定义了一系列规则,确保某些操作的有序性。


3. Happens-Before原则

Happens-Before是JMM中定义的一组规则,用于描述多线程环境下操作之间的可见性和有序性。以下是Happens-Before的主要规则:

  1. 程序顺序规则:在一个线程内,代码的执行顺序按照程序的书写顺序执行。

  2. 锁规则:一个unlock操作先行发生于后续对同一个锁的lock操作。

  3. volatile规则:对一个volatile变量的写操作先行发生于后续对这个变量的读操作。

  4. 线程启动规则Thread.start()先行发生于线程内的任何操作。

  5. 线程终止规则:线程中的所有操作先行发生于线程的终止检测(如Thread.join())。

  6. 传递性规则:如果A happens-before B,且B happens-before C,那么A happens-before C。


4. Volatile关键字

volatile是JMM中用于保证可见性和有序性的关键字。它的作用包括:

  1. 保证可见性:对volatile变量的修改会立即刷新到主内存,其他线程读取时会从主内存中获取最新值。

  2. 禁止指令重排序:JVM会禁止对volatile变量的读写操作进行重排序。

示例:
public class VolatileExample {
    private volatile boolean flag = false;

    public void writer() {
        flag = true;  // 写操作
    }

    public void reader() {
        if (flag) {  // 读操作
            System.out.println("Flag is true");
        }
    }
}

5. Synchronized关键字

synchronized是JMM中用于保证原子性、可见性和有序性的关键字。它的作用包括:

  1. 保证原子性:同一时刻只有一个线程可以执行同步代码块。

  2. 保证可见性:在释放锁之前,会将工作内存中的变量刷新到主内存。

  3. 保证有序性:同步代码块内的操作不会被重排序。

示例:
public class SynchronizedExample {
    private int count = 0;

    public synchronized void increment() {
        count++;  // 原子操作
    }

    public int getCount() {
        return count;
    }
}

6. Final关键字

final关键字用于修饰变量、方法和类。在JMM中,final关键字可以保证可见性:

  1. final变量:在构造完成后,对其他线程可见。

  2. final方法:不能被子类重写。

  3. final:不能被继承。

示例:
public class FinalExample {
    private final int value;

    public FinalExample(int value) {
        this.value = value;  // 构造完成后,value对其他线程可见
    }

    public int getValue() {
        return value;
    }
}

7. 内存屏障(Memory Barrier)

内存屏障是JMM中用于控制指令重排序和内存可见性的底层机制。常见的屏障包括:

  • LoadLoad屏障:确保前面的Load操作先于后面的Load操作。

  • StoreStore屏障:确保前面的Store操作先于后面的Store操作。

  • LoadStore屏障:确保前面的Load操作先于后面的Store操作。

  • StoreLoad屏障:确保前面的Store操作先于后面的Load操作。


8. 总结

Java内存模型(JMM)是理解Java并发编程的基础,它定义了多线程环境下线程如何与内存交互,以及如何保证原子性、可见性和有序性。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值