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

8 java concurrency multithreading synchronization

synchronized 方法synchronized 陈述有什么区别?

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

sgo*_*les 13

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

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


pol*_*nts 8

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

JLS 14.19 synchronized声明

一个synchronized说法获得代表执行线程的互斥锁,执行一个块,然后释放锁.当执行线程拥有锁时,没有其他线程可以获取锁.

JLS 8.4.3.6 synchronized方法

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

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

class Test {
    int count;
    synchronized void bump() { count++; }
    static int classCount;
    static synchronized void classBump() {
        classCount++;
    }
}
Run Code Online (Sandbox Code Playgroud)

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

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

那他们有什么不同?

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

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

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

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