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

问题描述 投票:0回答:5

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

如果可以的话,请举个例子来让它更清楚。

java multithreading concurrency synchronization
5个回答
14
投票

同步方法会锁定与类实例(即“this”)或类(如果是静态方法)关联的监视器,并阻止其他人这样做,直到该方法返回为止。同步块可以锁定任何监视器(您告诉它哪个),并且可以具有比封闭方法更小的范围。

如果同步块最终不等于方法的整个范围,和/或如果它们锁定的东西比实例(或类,如果是静态的)不那么严格,则首选同步块。


8
投票

引自JLS(包括示例):

JLS 14.19
synchronized
声明

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

JLS 8.4.3.6
synchronized
方法

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 第 2 版,第 67 条:避免过度同步:

通常,您应该在

synchronized
区域内做尽可能少的工作。

方法的

synchronized
修饰符本身就是一种语法糖,适用于许多但并非所有场景。本书更深入地讨论了为什么应该避免过度同步,但基本上通过使用
synchronized
语句,您可以更好地控制
synchronized
区域的边界(如果场景需要,您也可以选择您自己的锁)。

除非您的方法非常简单和/或您需要在方法的整个持续时间内获取

this
锁(如果方法是
Class
,则需要获取
static
对象锁),否则您应该使用
synchronized
语句将方法内的同步限制为仅在您需要时(即,当您访问共享的可变数据时)。


4
投票

synchronized
方法是一种其主体自动封装在
synchronized
块中的方法。

因此,这是相等的:

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

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

3
投票

synchronized
on 方法被锁定在
this
对象上。等于
synchronized (this) {}

标准

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


2
投票

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

© www.soinside.com 2019 - 2024. All rights reserved.