synchronized锁对象可以是:1.静态方法对应Class对象;2.实例方法对应this;3.同步代码块对应显式指定的任意对象。

可以使用 static final 修饰的专用锁对象,配合 synchronized 代码块,实现跨所有实例的严格同步。这不是靠 static 方法本身,而是靠一个被所有实例共享、不可变、专属的锁对象。
为什么不用 static synchronized 方法?
static synchronized 方法确实能实现类级别同步,但它的粒度是整个方法体——哪怕只有一行关键逻辑需要保护,其余非敏感代码也会被阻塞,降低并发吞吐。而很多场景只需保护一小段核心逻辑(比如更新全局计数器、写入静态缓存、初始化单例等),用方法级锁不划算。
- 它锁的是
MyClass.class,没错,但无法与其他同步操作解耦 - 若该类还有其他 static synchronized 方法,它们会互相竞争同一把类锁,造成不必要的串行化
- 无法灵活控制锁范围,也不便于做锁分离或读写分离
推荐做法:static final 锁对象 + 同步代码块
声明一个私有、静态、不可变的锁对象,只用于保护真正需要同步的那几行代码:
public class ResourceManager {
private static int globalCounter = 0;
private static final Object COUNTER_LOCK = new Object(); // ✅ 关键:static + final + private
public void updateResource() {
// 其他非敏感操作(可并发执行)
doPreCheck();
// ✅ 只锁核心敏感段
synchronized (COUNTER_LOCK) {
globalCounter++;
logUpdate(globalCounter);
}
// 其他后续操作(可并发执行)
notifyListeners();
}
}
-
COUNTER_LOCK是 static → 所有实例共享同一个对象引用 - 是 final → 引用不可变,杜绝意外重赋值导致锁失效
- 是 private → 防止外部误用或干扰,保证锁的专一性
- 用 synchronized(LOCK) 而非 synchronized(this) 或 synchronized(ResourceManager.class),语义清晰、职责单一
哪些对象不适合作为 static 锁?
避免使用可能被外部修改或复用的引用作为锁,否则会破坏同步契约:
-
String 字面量(如
synchronized("lock"))→ 字符串常量池共享,不同类可能无意中锁同一字符串 -
Integer/Long 等包装类常量(如
synchronized(Integer.valueOf(1)))→ 小整数自动缓存,存在隐式共享风险 - this 或 getClass() → 属于实例或反射结果,无法保证跨实例一致性
- public static 字段 → 外部可修改引用,锁对象可能被替换,失去同步效果
进阶提示:与 volatile / 原子类的配合
如果只是简单计数或状态标记,且操作是原子的(如自增、布尔切换),可优先考虑 AtomicInteger、AtomicBoolean 等,它们底层基于 CAS,无锁且性能更高:
private static final AtomicInteger globalCounter = new AtomicInteger(0);
public void updateResource() {
int newValue = globalCounter.incrementAndGet(); // ✅ 无锁、线程安全、高效
logUpdate(newValue);
}
但注意:原子类仅适用于“单个变量的简单操作”。一旦涉及多个变量的复合逻辑(如“先检查再更新”、“读-改-写”依赖多字段),就必须回归显式锁机制——这时 static final 锁对象就是最稳妥的选择。

















