内置锁重入在继承模型中的探讨

编程

在《Java并发编程实战》中讲解内置锁重入时,使用的示例如下:

public class Widget {

static {

System.out.println("super static init");

}

public Widget() {

System.out.println("super construct init");

}

pub lic synchronized void doSomething() {

System.out.println("super this is:" + this);

System.out.println("super do something");

}

}

class subWidget extends Widget {

public subWidget() {

System.out.println("sub construct init");

}

static {

System.out.println("sub static init");

}

@Override

public synchronized void doSomething() {

System.out.println("sub this is:" + this);

super.doSomething();

}

}

锁重入是很好理解的,这里的问题在于,引发了更深层次的虚拟机问题。搜索这段代码的理解,网上有很多讨论。首先synchronized修饰的实例方法,相当于synchronized(this),也就是当前对象的实例,如果这个例子成立的话,说明在父类Widget中的synchronized锁的就是子类实例,那么问题来了,众所周期,new一个子类实例时,会先执行父类的构造方法,这相当于实例化父类对象吗?这里调用super.doSomething()为什么锁的是子类实例?这个问题就没多少人能说得清楚了。

js">super static init

sub static init

super construct init

sub construct init

sub this is:com.skz.subWidget@1c655221

super this is:com.skz.subWidget@1c655221

super do something

为了验证结果,我们先执行一下代码,打印一下this,发现父类中this确实是指向subWidget对象。结论就是父类并没有实例化,所以以上内置锁代码成立。我们已经知道了结果,可是为什么呢?

要解决这个问题,就需要搞清楚类加载,类实例化,类继承的内存分配问题。关于这些问题的讲解,就只有一本《深入理解Java虚拟机》而已,书中解释了Java对象的内存分配,类加载过程,但是对于继承模型的内存情况以及实例化过程没有详细说明。以此书为据,说一下与问题相关的描述,这里要注意实例化与初始化的区别。

  • 类初始化:类加载过程即加载,验证,准备,解析,初始化,初始化是执行类构造器<clinit>()方法的过程,也就是执行类中的所有类成员变量的赋值语句和静态代码块,在初始化子类时,会首先保证父类的初始化。
  • 对象创建:类实例化之前,要先执行类加载过程。然后为新生对象分配内存,再执行必要的设置,如这个对象是哪个类的实例,元数据,GC分代年龄等。

通过在网上查找资料,java中,创建子类对象时,父类对象会也被一起创建么? ,这个回答下解释了为什么父类对象不会被创建,调用父类构造方法只是个初始化类实例变量的过程,并不能说明类对象被创建,这个问题的解释涉及到字节码文件结构及指令,这块内容在书中也有讲解,也许是深入理解之后得出的结论。图解Java继承内存分配 这篇文章解释了继承模型下的内存分配问题,super关键字用来引用被屏蔽的成员变量或成员方法,当然还是子类实例了。

至此,我们算是可以理解这个问题的答案了,但是,这些知识内容的源头在哪里呢?这明显没有出版物来解释这些问题,或许英文世界中有更权威的资料与探讨,就等待以后遇到问题再挖掘了。

以上是 内置锁重入在继承模型中的探讨 的全部内容, 来源链接: utcz.com/z/517789.html

回到顶部