对象的创建过程、DCL与Volatile之间的纠葛

简介: 对象的创建过程、DCL与Volatile之间的纠葛

正文


在我们写代码的过程中,我们很容易、很方便的就可以写出一个类,定义一些属性和方法。当我们使用的时候,直接新建new一个对象,或者想跳过范型检查的话,我们还可以利用反射的方式来创建我们的对象。那么在对象创建的时候,都发生了哪些事以及我们使用对象的时候,应该注意什么呢?


对象的创建过程


通常对象的对创建以及使用分为大致分为下面的几个过程:

21.png


加载:当我们进行创建对象的时候,比如使用new的时候,首先将去检查这个指令的参数是否能在常量池中定位到 一个类的符号引用,并且检查这个符号引用代表的类是否已被加载、解析和初始化过。如果没有,那必须先执行相应的类加载过程。

连接:这个过程分为三步,分别是:验证、准备以及解析。在这个过程中,Java虚拟机会进行对该对象进行空间分配,设置初值等。设置对象头,实例数据的初值,以及对齐补充数据。

初始化:在此之前,虽然Java虚拟机已经帮助我们实现了对象的空间分配以及设置默认值等操作,但是对于一些有值的属性会在初始化的时候进行赋值,也就是执行init()方法。执行完初始化的方法后,我们的对象就创建成功了,可以为以后的各个操作提供对象的实例。

使用:使用也是我们操作对象的过程。

卸载回收:使用完毕之后,Java虚拟机会自动的帮助我们将不用的对象内存进行回收。


DCL与Volatile之间的纠葛


DCL我们都知道,是我们使用懒汉式创建我们单例对象时候格式,也就是双重的检验。但是他与Volatile有什么关系呢?

我们在前面可知,在我们对象创建的连接的过程,Java虚拟机已经给我们分配了对象实例的内存大小以及地址,这个时候还没有进行初始化。初始化后,我们的对象实例就可以使用了。但是在多线程并发的时候,由于我们Java虚拟机会优化我们的指令的执行顺序,也就是指令的重排序,在单线程来看,我们的运行结果是没有问题的了。但是多线程的情况下们很有可能会发生我们的对象没有初始化就被其他的线程应用了。这就是对象逸出。

volatile的出现解决了这个问题,因为volatile可以实现指令的内存可见行以及禁止指令的重新排序。实现的方式采用的是内存屏障。有效的解决了我们前面所说的对象没有创建完就使用的情形。

相关文章
|
缓存 安全 Java
【JavaSE专栏78】线程同步,控制多个线程之间的访问顺序和共享资源的安全性
【JavaSE专栏78】线程同步,控制多个线程之间的访问顺序和共享资源的安全性
|
5月前
|
存储 安全 Java
Java面试题:Java内存模型中的主内存与工作内存是如何协同工作的?请解释Java内存模型中的可见性、原子性和有序性,举例说明Java内存模型中的happens-before关系
Java面试题:Java内存模型中的主内存与工作内存是如何协同工作的?请解释Java内存模型中的可见性、原子性和有序性,举例说明Java内存模型中的happens-before关系
36 0
|
12月前
|
安全 Java 编译器
Java并发编程学习3-可见性和对象发布
本篇介绍对象的共享之可见性和对象发布
88 2
Java并发编程学习3-可见性和对象发布
|
传感器 编译器
__weak关键字:程序模块相互独立的大杀器
__weak关键字:程序模块相互独立的大杀器
77 0
|
安全
多线程编程核心技术-对象及变量的并发访问-synchronize同步方法(2)(上)
多线程编程核心技术-对象及变量的并发访问-synchronize同步方法(2)(上)
111 0
多线程编程核心技术-对象及变量的并发访问-synchronize同步方法(2)(上)
|
数据采集 缓存 算法
库调多了,都忘了最基础的概念 《锁与线程 2 终结篇》
库调多了,都忘了最基础的概念 《锁与线程 2 终结篇》
138 0
库调多了,都忘了最基础的概念 《锁与线程 2 终结篇》
|
安全 Java Spring
重点丨什么是双重检查锁模式?以及为何需要 volatile 关键字?
双重检查锁定(Double check locked)模式经常会出现在一些框架源码中,目的是为了延迟初始化变量。这个模式还可以用来创建单例。下面来看一个 Spring 中双重检查锁定的例子。
重点丨什么是双重检查锁模式?以及为何需要 volatile 关键字?
|
存储 安全 Java
Java并发编程 - 有状态 & 无状态的对象区别
Java并发编程 - 有状态 & 无状态的对象区别
684 0