同步方法和块之间有什么区别?

时间:2010-04-28 09:43:41

标签: java multithreading concurrency synchronization

synchronized 方法synchronized 语句之间有什么区别?

如果可能,请使用示例使其更清晰。

5 个答案:

答案 0 :(得分:13)

synchronized方法锁定与类实例(即'this')或类(如果是静态方法)关联的监视器,并阻止其他人这样做,直到从方法返回。同步块可以锁定任何监视器(您告诉它哪个)并且可以使范围小于加载方法的范围。

如果同步块最终不等同于方法的整个范围和/或它们锁定的东西比实例(或静态类)更严格,则优先使用同步块。

答案 1 :(得分:8)

来自JLS的报价(包括示例):

JLS 14.19 The synchronized Statement

  

synchronized语句代表执行线程获取互斥锁,执行一个块,然后释放锁。当执行线程拥有锁时,没有其他线程可以获取锁。

JLS 8.4.3.6 synchronized Methods

  

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

     

这些锁是synchronized语句可以使用的锁;因此,代码:

class Test {
    int count;
    synchronized void bump() { count++; }
    static int classCount;
    static synchronized void classBump() {
        classCount++;
    }
}
     

具有与以下完全相同的效果:

class BumpTest {
    int count;
    void bump() {
        synchronized (this) {
            count++;
        }
    }
    static int classCount;
    static void classBump() {
        try {
            synchronized (Class.forName("BumpTest")) {
                classCount++;
            }
        } catch (ClassNotFoundException e) {
                ...
        }
    }
}

那么它们有何不同?

来自 Effective Java 2nd Edition 的引用,第67项:避免过度同步:

  

通常,您应该在synchronized区域内尽可能少地完成工作。

方法的synchronized修饰符,它是一种语法糖,适用于许多但不是所有场景。本书将更详细地讨论为什么要避免过度同步,但基本上通过使用synchronized语句,您可以更好地控制synchronized区域的边界(如果场景需要它的话) ,你也可以选择自己的锁。)

除非您的方法非常简单和/或您需要在方法的整个持续时间内获取this锁定(如果方法为Class,则需要static对象锁定) ,您应该使用synchronized语句将方法内的同步限制为仅在您需要时(即当您访问共享可变数据时)。

答案 2 :(得分:4)

synchronized方法是一种方法,其正文自动封装在synchronized块中。

因此,这是平等的:

public void foo()
{
    synchronized (this)
    {
        bar();
    }
}

public synchronized void foo()
{
    bar();
}

答案 3 :(得分:3)

方法上的

synchronized已锁定在this对象上。它等于synchronized (this) {}

标准synchronized已锁定在指定的对象/监视器上。使用synchronized (***) {},您可以选择用于锁定的对象。

答案 4 :(得分:2)

同步方法实际上是将函数的整个主体放在同步块中。同步块的优点是,您可以将synchronized块应用于函数中的几个select语句,而不是作为整体的函数。通常,最好使同步块尽可能短,因为在同步块中花费的时间是一些其他线程可能无法进行有意义的工作的时间。另一个区别是,您可以在使用synchronized块时指定要应用锁定的特定对象,而使用synchronized方法时,对象本身会自动用作执行同步的锁定。