Java中的synchronized方法和synchronized块之间有什么区别?

时间:2009-07-19 13:45:46

标签: java multithreading synchronization synchronized synchronized-block

Java中的synchronized方法和synchronized块之间有什么区别?

我一直在网上搜索答案,人们似乎对此不太了解: - (

我的看法是两者之间没有区别,除了同步块可能在范围内更局部化,因此锁定的时间会更短吗?

如果在静态方法上使用Lock,那么Lock是什么?锁定类的含义是什么?

6 个答案:

答案 0 :(得分:45)

synchronized方法使用方法接收器作为锁(即this用于非静态方法,而使用静态方法的封闭类)。 Synchronized块使用表达式作为锁。

因此,以下两种方法与锁定预期相同:

synchronized void mymethod() { ... }

void mymethod() {
  synchronized (this) { ... }
}

对于静态方法,该类将被锁定:

class MyClass {
  synchronized static mystatic() { ... }

  static mystaticeq() {
    syncrhonized (MyClass.class) { ... }
  }
}

对于同步块,您可以使用任何非null对象作为锁:

synchronized (mymap) {
  mymap.put(..., ...);
}

锁定范围

对于同步方法,锁将在整个方法范围内保持,而在synchronized块中,锁仅在该块范围内保持(也称为临界区)。实际上,如果JVM可以证明它可以安全地执行,则允许JVM通过从synchronized块执行中删除一些操作来进行优化。

答案 1 :(得分:8)

同步方法是简写。这样:

class Something {
    public synchronized void doSomething() {
        ...
    }

    public static synchronized void doSomethingStatic() {
        ...
    }
}
对于所有意图和目的,

等同于:

class Something {
    public void doSomething() {
        synchronized(this) {
            ...
        }
    }

    public static void doSomethingStatic() {
        synchronized(Something.class) {
            ...
        }
    }
}

(其中Something.class是类Something的类对象。)

事实上,使用同步块,您可以更加具体地了解锁定,并且在您想要使用它时更精细,但除此之外没有区别。

答案 2 :(得分:4)

是的,这是一个区别。另一个是你可以锁定this以外的其他对象。

答案 3 :(得分:2)

关键区别在于:如果声明要同步的方法,则方法的整个主体将变为同步;但是,如果使用同步块,则可以在同步块中仅包围方法的“临界区”,同时将方法的其余部分保留在块之外。

如果整个方法是关键部分的一部分,那么实际上没有区别。如果不是这种情况,那么您应该在关键部分周围使用同步块。同步块中的语句越多,您获得的整体并行性就越少,因此您希望将这些语句保持在最低限度。

答案 4 :(得分:0)

synchronized方法锁定方法所包含的对象实例。

同步块可以锁定任何对象 - 通常是定义为实例变量的互斥对象。这样可以更好地控制正在运行的锁。

答案 5 :(得分:0)

  

我的看法是两者之间没有区别,除了同步块可能在范围内更局部化,因此锁定的时间会更短吗?

是。你是对的。与synchronized方法不同,synchronized语句必须指定提供内部锁的对象。

java教程示例:

public void addName(String name) {
    synchronized(this) {
        lastName = name;
        nameCount++;
    }
    nameList.add(name);
}

同步语句对于通过细粒度同步提高并发性也很有用。您可以在以下用例的相同教程页面上找到很好的示例。

假设,例如,类MsLunch有两个实例字段,c1和c2,它们从不一起使用。这些字段的所有更新必须是synchronized,但没有理由阻止c1的更新与c2的更新交错 - 这样做会通过创建不必要的阻塞来减少并发性。 我们不是使用同步方法或使用与此相关联的锁,而是仅创建两个对象来提供锁

  

如果在静态方法上使用Lock,那么Lock是什么?锁定类的含义是什么?

在这种情况下,线程获取与类关联的Class对象的内部锁。因此,对类的静态字段的访问由与该类的任何实例的锁不同的锁控制。

当您将方法设为synchronized(非static)时:

同一对象上的两个synchronized方法调用不可能交错。当一个线程正在为对象执行同步方法时,所有其他线程都会调用同一对象的同步方法阻塞(暂停执行),直到第一个线程完成对象为止。

如果您将方法设为static synchronized

对同一类的不同对象进行两次static synchronized方法调用是不可能进行交错的。当一个线程正在为A类对象执行static synchronized方法时,所有其他线程在A类对象的任何对象上调用static synchronized方法(暂停执行),直到第一个线程完成方法执行。

在这个SE问题中,您找到了更好的同步替代方案:

Avoid synchronized(this) in Java?