Java中的并发:同步静态方法

Ami*_*hum 9 java multithreading synchronized

我想了解如何在Java中对静态方法进行锁定.

假设我有以下课程:

class Foo {
    private static int bar = 0;
    public static synchronized void inc() { bar++; }
    public synchronized int get() { return bar; }
Run Code Online (Sandbox Code Playgroud)

我的理解是,当我调用时f.get(),线程获取对象的锁定f,当我执行时Foo.inc(),线程获取类的锁定Foo.

我的问题是两个呼叫如何相互同步?调用静态方法也会获取所有实例化的锁定,或者相反(这似乎更合理)?


编辑:

我的问题并不完全是如何static synchronized工作的,但静态和非静态方法是如何相互同步的.也就是说,我不希望两个线程同时调用这两个f.get()Foo.inc(),但这些方法获得不同的锁.我的问题是这是如何可以预防的,并且在上面的代码中是否被阻止了.

axt*_*avt 9

静态和实例synchronized方法彼此无关,因此您需要在它们之间应用一些额外的同步,如下所示:

class Foo {
    private static int bar = 0;
    public static synchronized void inc() { bar++; }
    public synchronized int get() { 
        synchronized (Foo.class) { // Synchronizes with static synchronized methods
            return bar; 
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

(尽管在这种情况下,留下synchronizedget()没有任何意义,因为它没有做任何事情需要在实例同步).

注意死锁 - 因为这段代码需要多个锁,所以它应该按照一致的顺序执行,即其他同步的静态方法不应该尝试获取实例锁.

另请注意,使用原子字段可以在不进行同步的情况下解决此特定任务:

class Foo {
    private static AtomicInteger bar = new AtomicInteger(0);
    public static void inc() { bar.getAndIncrement(); }
    public int get() { return bar.get(); }
}
Run Code Online (Sandbox Code Playgroud)


Jon*_*eet 8

同步静态方法实际上等效于:

public static void foo() {
    synchronized (ClassName.class) {
        // Body
    }
}
Run Code Online (Sandbox Code Playgroud)

换句话说,它锁定Class与声明该方法的类相关联的对象.

JLS第8.4.3.6节开始:

同步方法在执行之前获取监视器(第17.1节).对于类(静态)方法,使用与方法类的Class对象关联的监视器.对于实例方法,使用与此关联的监视器(调用该方法的对象).