返回
Java 从入门到精通之内存模型
Android
2023-09-18 15:28:10
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 毫秒读取一次计数器值。由于 counter
是 volatile 变量,因此线程 2 可以看到线程 1 对 counter
的修改。
结论
Java 内存模型对于理解多线程编程非常重要。通过理解 Java 内存模型,我们可以避免出现数据竞争和死锁等问题。