37

Java中的同步方法和同步块有什么区别?

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

我的看法是两者之间没有区别,只是同步块可能在范围内更加本地化,​​因此锁定时间会更短?

如果在静态方法上使用 Lock,那么 Lock 是在什么情况下使用的?Lock on Class 是什么意思?

4

6 回答 6

45

同步方法使用方法接收器作为锁(即this用于非静态方法,以及用于静态方法的封闭类)。 Synchronizedblocks 使用表达式作为锁。

因此,从锁定角度来看,以下两种方法是等效的:

synchronized void mymethod() { ... }

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

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

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

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

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

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

锁定范围

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

于 2009-07-19T13:50:36.663 回答
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。)

因此,确实,使用同步块,您可以更具体地了解您的锁,并且更细粒度地了解何时使用它,但除此之外没有任何区别。

于 2009-07-19T13:50:57.897 回答
4

是的,这是一个区别。另一个是您可以获取除 之外的其他对象的锁this

于 2009-07-19T13:50:08.600 回答
2

关键的区别在于:如果你声明一个方法是同步的,那么整个方法体就会同步;但是,如果您使用同步块,那么您可以只将方法的“关键部分”包含在同步块中,而将方法的其余部分留在块之外。

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

于 2009-07-19T13:59:30.210 回答
0

同步方法锁定包含该方法的对象实例。

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

于 2009-07-19T13:53:16.397 回答
0

我的看法是两者之间没有区别,只是同步块可能在范围内更加本地化,​​因此锁定时间会更短?

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

java教程中的示例:

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

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

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

如果在静态方法上使用 Lock,那么 Lock 是在什么情况下使用的?Lock on Class 是什么意思?

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

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

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

如果您将方法设为static synchronized

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

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

在 Java 中避免同步(this)?

于 2016-09-13T17:55:35.227 回答