(JUC) Java并发面试题笔记

1. 什么是 Java 内存模型(JMM)? JMM 是 Java内存模型 , 它是Java虚拟机 JVM 定义的一种规范,用于描述多线程程序中的变量,像实例字段、静态字段和数组元素,他们如何在内存中存储和传递的规则。也就是规定线程啥时候从住内存里面读数据,啥时候把数据写回到住内存。JMM 的核心目标是确保多线程环境下的可见性、有序性和原子性, 避免硬件和编译器优化带来的不一致问题。 JMM 当中包含主内存 (所有线程共享) 和 工作内存 (每个线程私有)两种内存。 主内存:主内存是Java堆内存的一部分,是线程共享的区域,存储全局变量,比如静态变量、实例字段、数组元素等等。线程不能直接操作主内存,必须通过工作内存间接访问。 工作内存:每个线程私有的本地内存,缓存主内存的变量副本。线程对变量的读写操作均在工作内存种进行,修改后的结果需要同步会主内存。线程是通过内存屏障 ( volatile 关键字) 或者 同步操作 ( synchronized ) 实现主内存和工作内存的数据一致性的。 【可见性、有序性、原子性定义】 可见性:确保一个线程对共享变量的修改,能够及时被另外一个线程看到。 volatile就是用来保证可见性的,强制线程每次读写的时候,直接从主内存当中获取最新值。 有序性:指线程执行操作的顺序。JMM允许某些指令重排序之后再提高性能,但会保证线程内的操作顺序不会被破坏。通过happens-before (线程A发生在线程B之前)的关系来保证跨线程的有序性。 原子性:操作不可分割,线程不会在执行的过程当中被打断。例如, synchronize 关键字能确保方法或代码块的原子性 【JMM作用】 因为不同的操作系统都有一套独立的内存模型,但是Java为了满足跨平台的特性,它需要定义一套内存模型屏蔽个操作系统之间的差异。我们可以利用JMM当中定义好的从Java源码到CPU指令的执行规范,也就是使用synchronized 、volatile 等关键字,还有happens-before原则,就可以写出并发安全的代码了。 比如说,线程A和线程B同时操作 变量-1,假如最开始变量-1 是 0 首先,线程A和线程B都读取了变量-1 然后,线程B对取到的变量-1自增为1,并写回主内存 此时,线程A对读取到的变量-1也自增1,并写回主内存。这就会导致线程B的操作失效了,出现并发安全问题。 如果有JMM,我们就可以在线程A要修改数据之前,让它采用CAS乐观锁的方式进行修改。再次去读主内存当中的值,然后修改之后,再判断一下主内存的值是否发生变化。如果没有发生变化,就写回主内存。如果发生变化,就要进行自旋。 【注意】 工作内存是每个线程独立的内存空间,其他线程都是看不到的。主内存是Java堆内存的一部分,所有的实例变量、静态变量和数组元素都存储在主内存当中。 【内存间交互操作类型 (8种原子操作)】 lock 上锁:把一个变量表示为一条线程独占的状态 unlock 解锁: 把一个变量从独占状态中释放出来,释放后的变量才能被其他线程锁定 read 读取: 从主内存当中读取一个变量到工作内存中 load 载入:把read操作从主内存中得到的变量值放入工作内存的变量副本当中 use 使用:把工作内存当中的一个变量值传递给执行引擎 assign 赋值:把一个从执行引擎接收到的值赋给工作内存中的变量 store 存储:把工作内存中的一个变量的值传送给主内存中 write 写入:把store操作从工作内存中得到的变量值放入主内存的变量中 【volatile 特殊规则】 ...

March 5, 2025 · 14 min · SwimmingLiu