Java内存模型之JMM
1 大厂面试题
● 你知道什么是Java内存模型JMM吗?
JMM(Java内存模型Java Memory Model)本身是一种抽象的概念并不真实存在,它仅仅描述的是一组约定或规范,它定义了Java程序中多线程之间对共享变量的访问和操作的规则。通过这组规范定义了程序中(尤其是多线程)各个变量的读写访问方式并决定一个线程对共享变量的写入何时、如何变成对另一个线程可见,关键技术点都是围绕多线程的原子性、可见性和有序性展开的。
● JMM和volatile他们两个之间的关系?
JMM和volatile之间的关系在于,volatile关键字是JMM中实现变量可见性和禁止指令重排优化的一种机制。通过使用volatile关键字修饰变量,可以确保变量的修改对其他线程立即可见(可见性),并且防止因指令重排导致的线程安全问题(有序性).
● JMM三大特征是什么?
JMM(Java Memory Model)的三大特征是原子性、可见性和有序性。
原子性
原子性指的是一个操作是不可分割,不可中断的,一个线程在执行时不会被其他线程干扰。例如,对于一个静态全局变量的赋值操作,无论有多少个线程同时尝试修改它,该变量的值最终要么是其中一个线程赋予的值,要么是另一个线程赋予的值,不会出现中间状态。
可见性
可见性指的是当一个线程修改了某一个共享变量的值,其他线程是否能够立即知道这个修改。在多线程环境下,为了保证变量修改的可见性,Java提供了一些机制,如使用
volatile
关键字修饰变量,这样当一个线程修改了volatile
变量的值后,其他线程能够立即看到这个修改。有序性
有序性指的是程序的执行按照既定的顺序进行,不会出现乱序执行的情况。在单线程环境下,程序的执行通常是有序的。但在多线程环境下,由于编译器优化、处理器调度等因素,可能会导致指令重排,从而影响程序的执行顺序。Java通过
synchronized
关键字和volatile
关键字等机制来保证多线程环境下的有序性。这些特征共同构成了Java内存模型的核心,它们确保了Java程序在多线程环境下的正确性和稳定性。
● 为什么要有JMM,它为什么出现?作用和功能是什么?
JMM的出现原因
Java内存模型(Java Memory Model,JMM)是为了解决多线程编程中的内存一致性问题而设计的。在早期的编程语言如C和C++中,并没有内存模型的概念,程序的行为依赖于处理器本身的内存一致性模型,这导致相同的程序在不同的处理器上可能会有不同的行为。Java语言在设计之初引入了线程的概念,但最初的Java语言规范在内存模型方面存在缺陷,无法保证程序在不同的处理器架构上表现一致,也无法保证多线程程序的正确性。因此,Java迫切需要一个完善的JMM来解决这些问题。
JMM的作用和功能
JMM的主要作用和功能包括:
抽象线程和主内存的关系:JMM定义了线程和主内存之间的抽象关系,每个线程都有自己的工作内存,用于存放主内存中共享变量的副本。线程对变量的操作都在自己的工作内存中进行,只有在适当的时候,才会将工作内存中的变量副本写回主内存。
保证内存可见性:JMM通过happens-before关系来保证内存可见性,即一个操作的结果对另一个操作的可见性。例如,一个线程对共享变量的写操作,保证happen-before在随后对该变量的读操作。
避免指令重排:JMM允许编译器和处理器对指令进行重排,以提高程序的执行效率。但是,JMM通过happens-before关系和内存屏障等机制,禁止那些可能破坏程序正确性的重排序。
提供原子性保证:JMM通过锁和volatile关键字等机制,保证单个操作的原子性,即操作要么完全执行,要么完全不执行,不会被其他线程打断。
实现有序性