返回

Java 从入门到精通之内存模型

Android

Java内存模型概述

Java 内存模型是一种抽象的概念,它了多线程程序中共享变量的可见性和原子性。JMM 并不要求 JVM 实现特定的内存模型,而是提供了一组规则,JVM 必须遵守这些规则才能保证多线程程序的正确性。

内存可见性

内存可见性是指一个线程对共享变量的修改对其他线程是可见的。在 Java 中,内存可见性由 happens-before 关系来定义。happens-before 关系是一种偏序关系,它了在多线程程序中事件发生的顺序。如果事件 A happens-before 事件 B,那么 A 对共享变量的修改对 B 是可见的。

原子性

原子性是指一个操作要么完全执行,要么完全不执行。在 Java 中,原子性由 volatile 来实现。volatile 关键字可以保证对共享变量的修改对所有线程都是可见的,并且是原子的。

内存屏障

内存屏障是一种特殊的指令,它可以强制 JVM 在执行内存操作之前或之后刷新缓存。内存屏障可以用来保证内存可见性和原子性。

Java 内存模型示例

下面是一个 Java 内存模型的示例:

public class MemoryModelDemo {

    private volatile int counter = 0;

    public void incrementCounter() {
        counter++;
    }

    public static void main(String[] args) {
        MemoryModelDemo demo = new MemoryModelDemo();

        // 创建两个线程
        Thread thread1 = new Thread(() -> {
            // 线程 1 执行 1000 次自增操作
            for (int i = 0; i < 1000; i++) {
                demo.incrementCounter();
            }
        });

        Thread thread2 = new Thread(() -> {
            // 线程 2 每 100 毫秒读取一次计数器值
            while (true) {
                int value = demo.counter;
                System.out.println("Counter value: " + value);

                try {
                    Thread.sleep(100);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        });

        // 启动两个线程
        thread1.start();
        thread2.start();
    }
}

在这个示例中,线程 1 和线程 2 共享一个变量 counter。线程 1 执行 1000 次自增操作,而线程 2 每 100 毫秒读取一次计数器值。由于 countervolatile 变量,因此线程 2 可以看到线程 1 对 counter 的修改。

结论

Java 内存模型对于理解多线程编程非常重要。通过理解 Java 内存模型,我们可以避免出现数据竞争和死锁等问题。