什么是线程池?

线程池是池化技术的一种典型实现,所谓池化技术就是提前保存大量的资源,以备不时之需。在机器资源有限的情况下,使用池化技术可以大大的提高资源的利用率,提升性能等。

线程池,说白了就是提前创建好的一批线程,保存在线程池中,当有任务需要执行的时候,从线程池中选一个线程来执行任务。

在编程领域,比较典型的池化技术有:

线程池、连接池、内存池、对象池等。

什么是Java内存模型(JMM)?

Java 内存模型(Java Memory Model, JMM)是 Java 并发编程的核心规范,它定义了多线程环境下,线程如何与主内存(共享内存)及工作内存(线程私有内存)交互,以及如何保证多线程程序的可见性、有序性和原子性。JMM 的目的是解决多线程并发场景下的内存一致性问题。

JMM 的核心问题

  1. 可见性(Visibility)
    一个线程对共享变量的修改,其他线程是否能立即看到?
    问题:由于线程会将共享变量拷贝到自己的工作内存中操作,修改后可能不会立即同步回主内存,导致其他线程看到旧值。
    解决volatile 关键字、synchronizedfinalLock 等机制保证可见性。

  2. 有序性(Ordering)
    编译器和处理器可能会对指令进行重排序优化,导致代码执行顺序与编写顺序不一致。
    问题:重排序可能破坏多线程程序的预期逻辑(如单例模式的“双重检查锁定”问题)。
    解决volatile 禁止重排序、synchronizedhappens-before 规则。

  3. 原子性(Atomicity)
    一个操作是否不可中断?例如,简单的 i++ 操作实际上包含读、改、写三步,多线程下可能被其他线程干扰。
    解决synchronizedLock 或原子类(如 AtomicInteger)。

JMM 的核心概念

  1. 主内存(Main Memory)
    所有共享变量存储在主内存中,所有线程均可访问。

  2. 工作内存(Working Memory)
    每个线程有私有的工作内存,存储对共享变量的副本。线程对变量的操作(读/写)必须通过工作内存间接完成。

  3. 内存间交互
    JMM 定义了线程如何将主内存的变量拷贝到工作内存(loadread),以及如何将修改后的值同步回主内存(storewrite)。

happens-before 原则

JMM 通过 happens-before 规则定义操作的可见性和有序性,确保某些操作的结果对其他线程可见。以下是关键规则:

  1. 程序顺序规则
    同一线程内的操作,前边的操作 happens-before 后续任意操作。

  2. volatile 变量规则
    volatile 变量的写操作 happens-before 后续对它的读操作。

  3. 锁规则(监视器锁)
    解锁操作 happens-before 后续对同一锁的加锁操作。

  4. 传递性
    A happens-before B,且 B happens-before C,则 A happens-before C

  5. 线程启动规则
    线程的 start() 方法调用 happens-before 该线程的任何操作。

  6. 线程终止规则
    线程的所有操作 happens-before 其他线程检测到该线程已终止(如 Thread.join())。

为什么需要 JMM?

  • 不同硬件架构(如 CPU 缓存、指令重排序)的内存访问行为差异大,JMM 提供统一的抽象模型,屏蔽底层细节。

  • 开发者只需遵循 JMM 的规则(如正确使用同步机制),即可写出线程安全的代码。

注意

  • JMM 是规范,不是具体的物理内存结构。

  • 多线程编程必须通过 synchronizedvolatileLock 等机制保证可见性、有序性和原子性。