多线程同步疑问:为何不同对象线程调用类锁同步方法无法并发?
嘿,这个问题问到点子上了!刚好能帮你理清Java同步锁里一个很容易踩的坑~
为什么你的线程无法并发执行?
先给你吃个定心丸:你一开始的基础认知是完全正确的——非静态同步方法的锁是对象实例(比如你说的f1、f2),静态同步方法的锁是类的Class对象(Foo.class),这俩锁不是同一个,所以对应的线程确实能并发执行。
但你的代码示例里,问题出在所有线程都在争抢同一个锁对象,具体拆解下:
- 你写的
run()方法里用了synchronized(Foo.class),这就意味着:不管你创建多少个Foo的实例(f1、f2、f3...),只要线程进入这个run方法,都会去获取Foo.class这个类级别的锁。而在JVM里,一个类的Class对象是全局唯一的——整个应用里只有这一个Foo.class对象! - 所以哪怕你开了N个线程,分别绑定f1、f2这些不同的实例,它们最终都在抢同一个
Foo.class锁。同一时间只能有一个线程拿到锁执行同步块里的代码,自然没法并发。
举个反例帮你理解
如果想让不同实例的线程能并发,你只需要把同步锁改成当前实例对象就行:
class Foo implements Runnable{ public void run() { // 锁当前实例对象,每个Foo实例的锁都是独立的 synchronized(this) { // 你的业务代码 } } }
或者直接把run方法改成非静态同步方法(默认锁的就是this):
class Foo implements Runnable{ public synchronized void run() { // 你的业务代码 } }
这时候,f1的线程会抢f1实例的锁,f2的线程会抢f2实例的锁,两者互不干扰,就能实现并发执行了。
最后再划个重点
别混淆“手动指定锁对象”和“默认锁对象”:
- 如果你手动指定了
Foo.class作为锁,不管多少实例,锁都是同一个; - 只有当锁的是实例对象(比如this、f1、f2)时,不同实例的锁才是相互独立的。
内容的提问来源于stack exchange,提问作者ghostrider
相关产品推荐
相关产品推荐

