5

我正在阅读java中的静态方法同步。在我阅读的地方static methods获得了对象的锁定java.lang.class。我试图了解静态方法同步的概念java.lang.class及其在静态方法同步中的作用,但我有这些问题。

  1. 我正在阅读博客,其中说 Java 中的每个类都有一个实例,java.lang.Class并且一个类的所有实例共享这个对象。java.lang.Class 的实例描述了对象的类型?java.lang.Class在这里的作用是什么?它如何描述对象的类型?

  2. 其次对于静态方法同步,我们需要得到java.lang.Class的监听器。这是为什么?为什么我们需要锁定 java.lang.Class 监视器?为什么不在我们自己的类的实例上,例如 Test(我自己的自定义类)?

有人可以详细说明一下。我真的很抱歉,因为这听起来是一个非常基本的问题,但我对这个概念很陌生。

4

4 回答 4

4

试探性的解释,尽管不可否认它并不完全正确。对于任何课程C,当你这样做时:

final C c = new C();

Object这里涉及两个:Class<C>对象(通过上下文类加载器提供)和c实例。将通过其方法(在 中定义)c知道它是哪个类。.getClass()Object

new关键字能够建立正确的“反向链接”这一事实Class是 JVM 实现的责任。虽然 JLS 中肯定提到了这一点,但我不知道在哪里......

现在,更重要的是。

如果您有一个方法声明为:

synchronized void whatever() { someCode(); }

那么它大致相当于(为什么大致:见下文):

void whatever()
{
    synchronized(this) {
        someCode();
    }
}

也就是说,此代码在实例级别同步。

但是,如果该方法是静态的,则:

public static synchronized void meh() { someOtherCode(); }

大致相当于(为什么大致:见下文):

public static void meh()
{
    synchronized(getClass()) {
        someOtherCode();
    }
}

需要注意的一点是,所有Class对象都是单例;无论C您创建多少类实例,.getClass()都将始终返回相同的Class对象。尝试这个:

public static void main(final String... args)
{
    final String s1 = "foo";
    final String s2 = "bar";
    System.out.println(s1.getClass() == s2.getClass()); // true
}

getClass()添加相当于的事实,this.getClass()您就得到了图片。Class本身是一个Object,它遵守 any 的监控规则Object

而且由于这里我们总是引用完全相同的对象,因此应用了监控规则;)

现在,“大致”:在上面编写的代码中,逻辑是相同的;但是,根据您编写该代码的方式,字节码可能会有所不同;但 JIT 将有自己的发言权,并最终会优化代码路径。

于 2013-08-08T10:24:41.810 回答
1

java 中的每个对象都是某个类的一个实例。除此之外,每个也是一个对象,所以它也是某个类的一个实例

java.lang.Class 的实例描述了对象的类型?

不完全是。java.lang.Class类实例的一个

java.lang.Class在这里的作用是什么?它如何描述对象的类型?

它描述了所有类型的类型。

其次对于静态方法同步,我们需要得到java.lang.Class的监听器。这是为什么?为什么我们需要它的实例锁而不是我们的类锁?

您需要在某个对象上进行同步。根据定义,静态方法无法访问this,因此剩下的唯一共享内容就是定义它们的类

于 2013-08-08T10:23:59.040 回答
1

其次对于静态方法同步,我们需要得到java.lang.Class的监听器。这是为什么?为什么我们需要锁定 java.lang.Class 监视器?为什么不在我们自己的类的实例上,例如 Test(我自己的自定义类)?

有两种方法可以同步静态方法。一个是这样的:

static synchronized void methodName(){}

在这种情况下,用户不需要关心从外部获取锁。在内部,此类标记为已同步的所有静态方法都需要获取对其 java.lang.class 实例的锁定。在这种情况下很明显,instance(new Class()) 锁不能在这里获取,因为方法是静态的,静态方法可以在没有类的实例的情况下存在。该类的所有对象也共享静态方法。所以这个类的实例是没有问题的。

另一种方法是在静态方法中使用同步块:

    static void methodName() {

         synchronized(ClassName.class){ // same as above approach
         // method defination
         }

   synchronized(this){ } // not allowed. compile time error


   // to get lock of instance of this class you do as shown below. But it is not useful at all.  Because every time u acquire different instance. So synchronization is not achieved. 
synchronized(new Class()){ } 
       }

或者

static OtherClass lock = new OtherClass();
       static void methodName() {

             synchronized(lock){ // instance of other class can be used a well
             // method defination
             }
    }
于 2013-08-08T10:45:59.877 回答
0

该类java.lang.Class是您的类的代表。该类的主要用途Class是使用反射(例如获取构造函数和方法)。

为此,将其视为一个元对象......一个类的所有实例共享这个元对象。

Java 的设计者选择了监视器必须在对象上工作。要对静态方法进行监控,您必须使用上述元对象(或类)。

我认为这使得同步块监视器的设计和实现更容易。此外,如前所述,该类java.lang.Class用于反射,因此已经存在。

于 2013-08-08T10:20:11.587 回答