Java - 同步静态方法

时间:2013-03-11 01:04:41

标签: java static synchronization

以下是我在this链接中找到的一段文字。

  

“避免锁定静态方法

     

最糟糕的解决方案是将“synchronized”关键字置于静态   方法,这意味着它将锁定此类的所有实例。“

为什么同步静态方法会锁定类的所有实例?它不应该只是锁定类吗?

6 个答案:

答案 0 :(得分:33)

要理解这一点,最简单的方法是比较锁对实例方法和静态方法的工作原理。 假设你有类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无关,因为静态方法上的同步是类级别锁定。这意味着在释放锁定之前,tB根本无法访问 staticMethod

答案 1 :(得分:7)

实际上对类Foo的静态方法的锁定与对Foo.class(这是唯一的实例)的锁定相同:

public static void doSomething()
{
    synchronized(Foo.class)
    {
        // ...
    }
}

答案 2 :(得分:7)

这是我的测试代码,表明你是对的,文章有点过于谨慎:

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方法,那么您可以预期它们会对多线程系统的吞吐量产生最大影响,因此使用它们会带来危险......

答案 3 :(得分:4)

你是对的 - 实际锁定在Class实例本身,而不是在任何类的实例上(更不用说所有实例) - 但我认为你在解释链接页面太字面了。它本身使用短语“静态锁(类锁)”,所以很明显它的作者知道锁定是如何工作的。但是如果你在不同的线程中有很多实例都使用同步静态方法,那么这些实例将全部互相锁定。同步的静态方法不会导致阻塞同步的实例方法,但无论如何都存在问题。

答案 4 :(得分:2)

它没有说'锁定所有类的实例'。它在类的所有实例上都说'lock 。它的措辞很差,确实不正确,但它并没有说出你说的话。

答案 5 :(得分:2)

  

synchronized方法在执行之前获取监视器(第17.1节)。对于类(静态)方法,使用与方法类的Class对象关联的监视器。对于实例方法,使用与此关联的监视器(调用该方法的对象)。

http://docs.oracle.com/javase/specs/jls/se7/html/jls-8.html#jls-8.4.3.6