synchronized 通过强制串行化访问确保共享变量读-改-写操作不被交错执行,避免竞态条件导致的数据错乱;它同时保障原子性和可见性,类锁保护静态变量,实例锁保护同一对象的成员变量。

Java 中 synchronized 不是“防止变量被污染”,而是通过强制串行化访问,确保对共享变量的读-改-写操作不被多个线程交错执行,从而避免数据错乱。
为什么共享变量会“被污染”
所谓“污染”,本质是竞态条件(Race Condition):多个线程同时读取同一变量值 → 各自计算 → 再写回,导致部分更新被覆盖。例如两个线程对静态 int counter = 0 各执行一次 counter++,结果可能仍是 1 而非 2。这是因为 counter++ 包含三个非原子步骤:
– 从主内存读取值到线程工作内存
– 在工作内存中加 1
– 将结果写回主内存
中间任意一步被其他线程打断,就会出错。
类锁保护静态共享变量
当共享变量是 static 的(属于类,所有实例共用),必须使用类级别的锁来协调访问:
在 Java 中初始化和管理阿里云 SDK客户端。包括单例模式、线程安全、endpoint 与 region 配置、VPC 终端节点、同步与异步等。
- 修饰静态方法:
public static synchronized void increment() { counter++; }→ JVM 自动以MyClass.class为锁对象 - 同步代码块:
synchronized (MyClass.class) { counter++; }→ 显式指定类锁,粒度更灵活,适合只保护关键段 - 所有线程无论通过哪个实例调用,都竞争同一把锁,天然互斥
- 不能写
synchronized(counter)—— 基本类型或引用值不是锁载体,编译直接报错
实例锁保护成员变量
若共享变量是实例字段(如 private int balance),且多个线程操作的是同一个对象实例,可用实例锁:
- 修饰实例方法:
public synchronized void withdraw(int amount) { balance -= amount; }→ 锁住this - 同步代码块:
synchronized(this) { balance -= amount; } - 注意:若线程操作的是不同实例,
this锁彼此无关,无法保护共享状态 —— 此时应改用类锁或统一锁对象
它同时解决两个关键问题
synchronized 不只是“排队执行”,还配套保障了 Java 内存模型要求的同步语义:
- 原子性:整个同步块内操作不可分割,不会被线程切换打断
- 可见性:进入同步块前,强制从主内存刷新变量最新值;退出时,强制将修改写回主内存 —— 其他线程后续进入同一锁区域时,必然看到之前线程的全部修改
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










