You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

多线程同步疑问:为何不同对象线程调用类锁同步方法无法并发?

嘿,这个问题问到点子上了!刚好能帮你理清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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.27 04:20:51