热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

我所理解的JMM2new原子性

概述文本探讨构造函数是否为原子性问题。案例我们首先如下代码:publicclassPerson{publicintage;publicPerson(){age

概述

文本探讨构造函数是否为原子性问题。


案例

我们首先如下代码:

public class Person {public int age;public Person() {age=20;}
}//构造对象
public class JavaMain {public static void main(String[] args) {Person person = new Person();}
}

请问Person person = new Person();是否为原子性操作?
下图为main函数的字节码:
在这里插入图片描述
我们可以看到构建一个类大致可以分为4步骤:


  1. new指令申请堆栈空间,并且会生成一个引用放入函数的栈帧的栈顶。
  2. dup复制栈顶,那么此处会在栈顶存在两个Person堆内存地址引用.
  3. invokespecial 弹窗栈顶Person并调用初始化函数
  4. 将栈顶的剩余的Person引用弹窗复制到本地变量槽1中

可见一个构造一个对象并非原子性操作,那么这会带来哪些多线程问题?

public class JavaMain {static Person person;public static void main(String[] args) {new Thread("Thread One") {@Overridepublic void run() {super.run();person = new Person();}}.start();new Thread("Thread Two") {@Overridepublic void run() {super.run();if (person != null) {System.out.println(person.age);}}}.start();}
}

上面会发生 data race(数据竞争)情况,上面的代码在极端情况可能会输出0.

原因调用初始化函数步骤 和将栈顶引用复制回Mainperson发生了重排序。

在这里插入图片描述
解决方案一:
利用Pesronage字段使用final修饰.

public class Person {final public int age;public Person() {age = 20;}
}

关于final语义后文讲解.

其他解决方案:
1.同步锁
2.volatile修饰
3.利用happer-before关系防止重排序(volatile原理)
4. 略


推荐阅读
author-avatar
今生绝恋2702934494
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有