synchronized和static synchronized之间有什么区别

时间:2014-06-19 10:30:26

标签: java multithreading static synchronized

好吧,我发现这个问题已经回答了几次。答案也很常见。 静态同步方法锁定 Class ,其中synchronized方法锁定实例本身。

同一类的两个不同的线程不能同时调用两个不同的同步方法。如果呼叫则阻止一个。 静态同步方法也会发生同样的事情。因此在我看来,两种情况都表现出相同的可用性。如果有人在这两种方法的可用性方面有所区别,那将会非常有帮助。

2 个答案:

答案 0 :(得分:1)

  

同一类的两个不同的线程不能同时调用两个不同的同步方法。

这是一种非常常见的误解,但并非总是如此。这里的总是是什么:同一个对象上没有两个线程可以synchronized

在实例方法上使用synchronized关键字时,方法的整个主体将在this上同步。假设我们有一个班级:

class Foo {
    synchronized void doSomething() { ... }
    synchronized void doSomethingElse() { ... }
}

这实际上是写这篇文章的简写方式:

class Foo {
    void doSomething() { synchronized (this) { ... }}
    void doSomethingElse() { synchronized (this) { ... }}
}

现在假设我们有两个类的实例:

final Foo f1 = new Foo(...);
final Foo f2 = new Foo(...);

当线程B在f1.doSomethingElse()中时,线程A不可能输入f1.doSomething(),但是线程A输入f1.doSomething()时 是可能的线程B在f2.doSomethingElse()中。这是因为f1和f2是不同的对象。 synchronized关键字仅阻止两个或多个线程在相同的对象上进行同步。

static方法的情况略有不同。这个声明:

class Bar {
    static synchronized void doSomething() { ... }
    static synchronized void doSomethingElse() { ... }
}

与此声明相同:

class Bar {
    static void doSomething() { synchronized(Bar.class) { ... }}
    static void doSomethingElse() { synchronized(Bar.class) { ... }}
}

static方法无法在this上同步,因为未为静态方法定义this。静态方法改为在类对象上同步。

在这种情况下,一个线程在Bar.doSomething()中是永远不可能,而另一个线程在Bar.doSomethingElse()中运行,因为两个方法在同步< / em> object(Bar.class对象。)

答案 1 :(得分:0)

在下面的代码中

  • 不允许两个线程同时进入b方法。
  • 不允许两个线程同时进入t1.a()方法。
  • 调用t1.a()的一个帖子会干扰另一个调用t2.a()的帖子。

    public class Test {
    
        synchronized void a() {
    
        }
    
        static synchronized void b() {
    
        }
    
        public static void main(String args[]) {
            final Test t1 = new Test();
            final Test t2 = new Test();
            // Some threads that just mess with the test objects.
            Thread test1 = new Thread() {
                public void run() {
                    while (true) {
                        t1.a();
                    }
                }
            };
            Thread test2 = new Thread() {
                public void run() {
                    while (true) {
                        t2.b();
                    }
                }
            };
            Thread test3 = new Thread() {
                public void run() {
                    while (true) {
                        t1.a();
                        t1.b();
                        t2.a();
                        t2.b();
                    }
                }
            };
            test1.start();
            test2.start();
            test3.start();
        }
    }