如何在Java中实现类级别锁定?

应克服

我知道通过同步静态和非静态方法来分别锁定类和实例的锁定概念。我不明白的是,如何实现类级别的锁定?我的意思是,课堂只是一个模板,没有任何物理意义。那么,当我们说通过同步静态方法来实现类级别锁定时,会发生什么呢?该类的所有对象都被锁定或进行其他处理吗?

通过搜索可以发现,存在类对象(Class.class),并且在该类对象上获得了锁。但是,该类的所有实例又如何被锁定?

所罗门慢

该类的所有对象都被锁定或进行其他处理吗?

首先,让我们谈谈“锁定”对象的含义。

Foobar foobar = new Foobar();

synchronized (foobar) {
    ...
}

您可能会说,在synchronized块中有线程时,foobar对象已“锁定” 但这对程序有什么作用?许多新手都会犯这样一个错误,即认为它将阻止其他线程访问该对象。但是,那是正确的。是什么synchronized呢-同步的唯一的事情那样-是要保证不超过一个线程可以对同一对象在同一时间同步。

上面示例中的程序员的意图可能是防止其他线程看到状态不一致的foobar。在这种情况下,访问foobar的每个方法和代码片段都必须在foobar上同步。将foobar想象成有许多门的大房间。每个使用foobar的方法都像一扇不同的门。如果您想将人们拒之门外,只锁一扇门是无济于事的。您必须锁定所有这些。

所以,现在,您的问题是:

当我们说通过同步静态方法实现类级别锁定时,会发生什么?

简单的。这:

class Foobar {
    static synchonized void do_something() {
        ...
    }
}

与此完全相同:

class Foobar {
    static void do_something() {
        synchronized(Foobar.class) {
            ...
        }
    }
}

您始终在对象上进行同步。好吧,一个类就是一个对象。static方法为时synchronized,这仅意味着方法主体在类对象上同步。

由于类是单例对象,因此这意味着没有两个线程可以同时进入同一静态同步方法。在我之前的示例中,变量foobar可以在不同的时间引用不同的对象,但是在静态示例中,保证Foobar.class始终引用同一单例。


编辑:@Danny指出,在Foobar类上同步的块(我的第二个示例)与在Foobar类实例同步的块(我的第一个示例)之间没有连接。实例和类对象是两个不同的对象,因此没有什么可以阻止一个线程在实例上进行同步,而另一个线程可以在类上进行同步。同样,没有什么可以阻止两个不同的线程在两个不同的实例上同步。新手经常犯的另一个错误是认为一次只能有一个线程可以进入此synchronized块:

Integer n = ...;

synchronized (n) {
    n = n+1;
    ...
}

但这不是真的。不是变量n被锁定,而是Integer类的特定实例。每个进入该块的线程都会创建一个新的Integer实例,并将其分配给n。因此,当下一个线程出现时,n不再引用第一个线程已同步的同一实例。

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章