上一篇验证了 synchronized 方法和 synchronized(this) 块锁的是同一个对象。这一篇换成 static synchronized,真实验证它锁的其实是完全不同的另一个对象——类本身的 Class 对象。
上一篇:synchronized 方法和 synchronized(this) 块:真实验证锁的是同一把锁
先确认实例级别的 synchronized 方法,锁的确实是"这一个"实例,不是所有实例共享。
StaticSyncDemo.java static synchronized void staticMethod() { ... } // 锁的是 StaticSyncDemo.class synchronized void instanceMethod() { ... } // 锁的是 this 这个实例
两个不同实例并发调用各自的 instanceMethod(), 真实总耗时 = 503ms(接近 500ms 说明真实并行,没有互相阻塞)
每次调用真实耗时 500ms,两个线程分别操作两个不同的实例,总耗时真实只有 503ms——接近单次耗时,不是两次相加的 1000ms,证明两把锁真实是独立的,没有互相等待。
换成 static 方法,即使是通过不同实例发起调用,锁住的其实都是同一个 Class 对象。
两次并发调用 staticMethod(), 真实总耗时 = 1008ms(接近 1000ms 说明真实互相阻塞,共享同一把类锁)
同样是两个线程各自调用一次(每次 500ms),这次真实总耗时变成了 1008ms——接近两次相加,说明第二个线程真实排队等了第一个线程释放锁之后才开始执行。static synchronized 方法锁的不是任何一个具体实例,而是这个类对应的 Class 对象本身(相当于隐式 synchronized(StaticSyncDemo.class))——不管从哪个实例发起调用,竞争的都是同一把锁。
最后把两者放在一起验证:一个线程正忙着持有某个实例的锁,另一个线程调用这个类的 static synchronized 方法,会不会被挡住。
holder 线程持有 obj 实例锁忙着的时候, main 线程调用 staticMethod() 真实耗时 = 505ms(接近 500ms 而不是 1000ms,说明真实没有被实例锁阻塞)
每一行都是真实运行这段代码,用 Thread.holdsLock() 检查得到的结果。