这是我在此链接上找到的一段文字。
避免锁定静态方法
最糟糕的解决方案是在静态方法上放置“synchronized”关键字,这意味着它将锁定该类的所有实例。
为什么同步静态方法会锁定类的所有实例?它不应该只锁定Class吗?
这是我在此链接上找到的一段文字。
避免锁定静态方法
最糟糕的解决方案是在静态方法上放置“synchronized”关键字,这意味着它将锁定该类的所有实例。
为什么同步静态方法会锁定类的所有实例?它不应该只锁定Class吗?
要理解这一点,最简单的方法是比较锁对实例方法和静态方法的工作方式。假设你有一个Test.java类,其中包含以下两个方法。
public class Test{
public synchronized void instanceMethod(){
}
public synchronized static void staticMethod(){
}
}
同时,有两个Test类的实例testA和testB,还有两个线程tA和tB并行尝试访问Test类。
在instanceMethod上加锁: 当tA获取testA的instanceMethod的锁时,tB无法访问testA中相同的方法。然而,tB仍然可以自由地调用testB中的instanceMethod,因为对instanceMethod进行同步是基于实例级别的锁定。
在staticMethod上加锁: 然而,当tA获取staticMethod的锁时,锁与testA或testB无关,因为对静态方法的同步是基于类级别的锁定。这意味着直到tA释放锁之前,tB无法访问staticMethod。
实际上,对于类Foo
的静态方法进行锁定,与对Foo.class
(唯一实例)进行锁定相同:
public static void doSomething()
{
synchronized(Foo.class)
{
// ...
}
}
这是我的测试代码,证明您是对的,而文章有点过于谨慎:
class Y {
static synchronized void staticSleep() {
System.out.println("Start static sleep");
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
}
System.out.println("End static sleep");
}
synchronized void instanceSleep() {
System.out.println("Start instance sleep");
try {
Thread.sleep(200);
} catch (InterruptedException e) {
}
System.out.println("End instance sleep");
}
}
public class X {
public static void main(String[] args) {
for (int i = 0; i < 2; ++i) {
new Thread(new Runnable() {
public void run() {
Y.staticSleep();
}
}).start();
}
for (int i = 0; i < 10; ++i) {
new Thread(new Runnable() {
public void run() {
new Y().instanceSleep();
}
}).start();
}
}
}
输出:
Start instance sleep
Start instance sleep
Start instance sleep
Start instance sleep
Start instance sleep
Start static sleep
Start instance sleep
Start instance sleep
Start instance sleep
Start instance sleep
Start instance sleep
End instance sleep
End instance sleep
End instance sleep
End instance sleep
End instance sleep
End instance sleep
End instance sleep
End instance sleep
End instance sleep
End instance sleep
End static sleep
Start static sleep
End static sleep
因此,static synchronized
与实例的 synchronized
方法无关...
当然,如果在整个系统中广泛使用 static synchronised
方法,则可以预期它们将对多线程系统的吞吐量产生最大影响,因此要谨慎使用...
Class
实例本身,而不是类的任何实例(更不用说所有实例)——但我认为你过于字面理解所链接的页面了。它本身使用了短语“静态锁(Class锁)”,因此其作者显然知道锁定的工作原理。但如果你有许多不同线程中的实例都在使用同步静态方法,则这些实例将相互阻塞。同步的静态方法不会导致同步的 实例 方法的阻塞,但问题仍然存在。它并没有说“锁定类的所有实例”,而是说“在类的所有实例上锁定”。这种措辞很糟糕,实际上是不正确的,但它并没有像你所说的那样。
http://docs.oracle.com/javase/specs/jls/se7/html/jls-8.html#jls-8.4.3.6