Java 内存模型(JMM)是一个抽象概念,它规定了在Java并发编程中如何处理多线程之间的内存交互。JMM 解决并发程序中最关键的两个问题:线程间的可见性和指令重排序。
线程间的可见性:确保当一个线程修改了共享变量的值时,其他线程可以立即看到这一改变。没有良好的可见性保证,一个线程对共享变量的修改可能对其他线程不可见,导致数据不一致。
指令重排序:为了提高性能,编译器和处理器常常会改变指令的执行顺序(只要这种改变不影响单线程内的程序逻辑)。然而,在多线程环境下,这种重排序可能导致严重问题。
JMM 通过以下几种方式来控制和协调上述现象:
-
原子性(Atomicity): JMM 保证了基本读取和写入操作的原子性。例如,对于声明为 volatile 的变量,其读和写操作都是原子的。
-
可见性(Visibility): 为了确保一个线程对共享变量所做的修改可以被其他线程看到,JMM 引入了 volatile 关键字和锁(synchronization)。当一个变量被声明为 volatile 后,对这个变量的修改立即会刷新到主内存,其他线程读这个变量也会直接从主内存读取。
-
有序性(Ordering): 即便是在无依赖的操作中,JMM 也禁止编译器和处理器进行重排序。通过 synchronized 和 volatile 关键字,以及 final 字段,JMM 可以在特定条件下避免指令重排序。
happens-before 原则:
Happens-Before规则是Java内存模型(JMM)中的一个重要概念,用于描述多线程环境下操作之间的顺序和可见性。如果操作A happens-before操作B,那么JMM保证A的结果对B可见,并且A的操作顺序在B之前。这个规则提供了一种跨线程内存操作的可预测性,帮助程序员编写正确的并发代码。一些关键的happens-before规则包括:
-
程序顺序规则:在一个线程内,每个操作都happens-before于该线程中的任意后续操作。
-
监视器锁规则:对一个锁的解锁happens-before于随后对这个锁的加锁。
-
volatile变量规则:对一个volatile字段的写入happens-before于任何后续对这个volatile字段的读取。
-
线程启动规则:Thread对象的start()方法happens-before于此线程的每一个动作。
-
线程终结规则:线程中的所有操作都happens-before于对此线程的终结检测,我们可以通过Thread.join()方法结束、Thread.isAlive()的返回值等手段进行检测。
-
中断规则:对线程interrupt()的调用happens-before于被中断线程检测到中断事件的发生。
-
传递性:如果A happens-before B,且B happens-before C,那么A happens-before C。
总结:由于 Java 并发编程复杂性很高,JMM 提供了一套规则让开发者在多线程环境下编写出能够正确交互的代码。尽管 JMM 不直接涉及垃圾收集和其他内存管理方面,了解 JMM 对于理解内存操作的并发问题非常关键。
标签:happens,模型,线程,内存,JMM,volatile,before From: https://blog.csdn.net/weixin_53391173/article/details/139499384