什么是线程池?
线程池是池化技术的一种典型实现,所谓池化技术就是提前保存大量的资源,以备不时之需。在机器资源有限的情况下,使用池化技术可以大大的提高资源的利用率,提升性能等。
线程池,说白了就是提前创建好的一批线程,保存在线程池中,当有任务需要执行的时候,从线程池中选一个线程来执行任务。
在编程领域,比较典型的池化技术有:
线程池、连接池、内存池、对象池等。
什么是Java内存模型(JMM)?
Java 内存模型(Java Memory Model, JMM)是 Java 并发编程的核心规范,它定义了多线程环境下,线程如何与主内存(共享内存)及工作内存(线程私有内存)交互,以及如何保证多线程程序的可见性、有序性和原子性。JMM 的目的是解决多线程并发场景下的内存一致性问题。
JMM 的核心问题
可见性(Visibility)
一个线程对共享变量的修改,其他线程是否能立即看到?
问题:由于线程会将共享变量拷贝到自己的工作内存中操作,修改后可能不会立即同步回主内存,导致其他线程看到旧值。
解决:volatile
关键字、synchronized
、final
或Lock
等机制保证可见性。有序性(Ordering)
编译器和处理器可能会对指令进行重排序优化,导致代码执行顺序与编写顺序不一致。
问题:重排序可能破坏多线程程序的预期逻辑(如单例模式的“双重检查锁定”问题)。
解决:volatile
禁止重排序、synchronized
或happens-before
规则。原子性(Atomicity)
一个操作是否不可中断?例如,简单的i++
操作实际上包含读、改、写三步,多线程下可能被其他线程干扰。
解决:synchronized
、Lock
或原子类(如AtomicInteger
)。
JMM 的核心概念
主内存(Main Memory)
所有共享变量存储在主内存中,所有线程均可访问。工作内存(Working Memory)
每个线程有私有的工作内存,存储对共享变量的副本。线程对变量的操作(读/写)必须通过工作内存间接完成。内存间交互
JMM 定义了线程如何将主内存的变量拷贝到工作内存(load
、read
),以及如何将修改后的值同步回主内存(store
、write
)。
happens-before 原则
JMM 通过 happens-before
规则定义操作的可见性和有序性,确保某些操作的结果对其他线程可见。以下是关键规则:
程序顺序规则
同一线程内的操作,前边的操作happens-before
后续任意操作。volatile 变量规则
对volatile
变量的写操作happens-before
后续对它的读操作。锁规则(监视器锁)
解锁操作happens-before
后续对同一锁的加锁操作。传递性
若A happens-before B
,且B happens-before C
,则A happens-before C
。线程启动规则
线程的start()
方法调用happens-before
该线程的任何操作。线程终止规则
线程的所有操作happens-before
其他线程检测到该线程已终止(如Thread.join()
)。
为什么需要 JMM?
不同硬件架构(如 CPU 缓存、指令重排序)的内存访问行为差异大,JMM 提供统一的抽象模型,屏蔽底层细节。
开发者只需遵循 JMM 的规则(如正确使用同步机制),即可写出线程安全的代码。
注意
JMM 是规范,不是具体的物理内存结构。
多线程编程必须通过
synchronized
、volatile
、Lock
等机制保证可见性、有序性和原子性。