synchronized 锁的是对象实例而非代码,非静态方法锁this、静态方法锁类class对象,显式同步块锁指定对象,不同对象间无竞争。

可以这样跟新手说:synchronized 锁住的不是“哪几行代码”,而是“调用这些代码的那个对象”。关键在于“谁在调用”,而不是“写了什么代码”。
锁的是对象实例,不是方法或代码块本身
比如你写了一个方法:
public synchronized void doSomething() { ... }
这看起来像“锁住了这个方法”,其实等价于:
public void doSomething() { synchronized(this) { ... } }
也就是说,真正被锁的是当前对象(this),也就是调用这个方法的那个实例。两个线程分别操作两个不同的对象实例,即使调用的是同一个方法,也不会互相阻塞。
同一个对象,才会产生竞争
假设你有:
- Object obj1 = new Counter();
- Object obj2 = new Counter();
线程 A 调用 obj1.doSomething(),线程 B 同时调用 obj2.doSomething() —— 它们互不影响,因为锁的是不同对象。
但若都是调用 obj1.doSomething(),那第二个线程就得等第一个执行完释放锁。
静态方法是个例外:锁的是类对象
如果写的是:
public static synchronized void doStatic() { ... }
那就等价于:
synchronized(Counter.class) { ... }
这时锁的是 Counter 类对应的 Class 对象,所有该类的实例共享这一把锁。所以静态同步方法和非静态同步方法之间,默认不互斥——它们锁的根本不是同一个东西。
自己显式加锁时,更能看清“锁谁”
比如:
synchronized(lockA) { ... }<br>synchronized(lockB) { ... }
这里一目了然:前一段锁的是 lockA 这个对象,后一段锁的是 lockB 这个对象。只要 lockA 和 lockB 是两个不同的对象,两段代码就能并发执行。
哪怕它们在同一个方法里、代码完全一样,锁的对象不同,效果就完全不同。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











