Java基本类型不能直接加锁,需用同步块、volatile或原子类保护;包装类不可变且缓存,不可作锁对象,共享时应改用原子类或封装同步。

Java 基本类型(如 int、boolean、long)本身不是对象,不能直接加锁或作为同步目标;包装类(如 Integer、Boolean)虽是对象,但不可变且常被缓存,**也不能直接用作锁对象**。多线程下安全使用的关键,不是“同步类型”,而是**控制对变量的读写操作过程**——尤其要防范非原子操作(如 count++)和可见性问题。
基本类型:用同步块、volatile 或原子类保护
基本类型变量必须通过外部机制保障线程安全:
-
复合操作(如自增、条件更新)必须用同步块或同步方法:因为
count++拆解为“读→改→写”三步,中间可能被其他线程打断。推荐用私有锁对象,避免锁膨胀或意外共享:
// 推荐写法:专用锁对象
private final Object lock = new Object();
public void increment() {
synchronized(lock) { count++; }
}
-
仅需保证可见性(如开关标志位),用
volatile:它禁止指令重排序,确保写操作对其他线程立即可见,但不提供原子性。适用于isRunning = true这类单次赋值场景。 -
高频读写且追求性能,优先选原子类:如
AtomicInteger、AtomicBoolean。它们基于 CAS 实现无锁原子操作,比 synchronized 更轻量:
private AtomicInteger count = new AtomicInteger(0);
public void increment() { count.incrementAndGet(); }
分析 Java Spring Boot 后端 Controller 代码,自动生成 Markdown 格式的接口文档。当用户说“生成 Java 接口文档”、“生成 API 文档”、“从 Spring 代码生成文档”时触发。
包装类:别拿它当锁,也别直接共享可变状态
包装类对象(如 new Integer(100) 或 Boolean.TRUE)是不可变的,每次修改都会生成新对象。这意味着:
-
不能用
Integer等作为synchronized的锁对象:因为Integer.valueOf(127)会复用缓存对象,不同实例可能锁住同一对象,造成意外交互;而new Integer(128)又每次新建,失去锁意义。 -
不要把包装类变量当作共享计数器来直接 ++:例如
Integer count = 0; count++;实际是拆箱→计算→装箱→赋值,全程非原子,且引用已变更,其他线程看不到更新。 -
若需共享状态,应封装+同步,或改用原子类:比如用
AtomicInteger替代Integer字段;若必须用包装类字段,就把它放在同步块内读写,并确保所有访问路径一致。
静态基本类型/包装类变量:注意类级别锁与初始化安全
静态变量属于类,多个实例共享同一份数据,风险更高:
立即学习“Java免费学习笔记(深入)”;
- 同步时建议用
MyClass.class或专用静态锁对象,避免实例锁失效; - 静态变量的初始化(尤其带逻辑的)要防双重检查失效,推荐用
static块或final+ 初始化表达式,必要时配合volatile(如单例中的 instance 字段); - 像
static Integer counter = 0;这种写法本质仍是非线程安全的,应替换为static AtomicInteger counter = new AtomicInteger(0);。
什么时候可以不用同步?
以下情况天然线程安全,无需额外处理:
- 变量只在单个线程内创建和使用(如方法内局部变量);
- 变量声明为
final且引用不可变对象(如final String name = "Tom";); - 使用不可变集合或只读视图(如
Collections.unmodifiableList(...)); - 每个线程操作自己独立副本(如
ThreadLocal<integer></integer>)。

















