线程安全>JVM内存模型>JAVA类加载

1.servlet为什么不是线程安全的?

例子:

.......

public   int count = 0 ;

doPost(){}

doGet(){}

......

相信面试的时候除了问servlet的生命周期外,肯定会问到servlet是不是线程安全的?

不是线程安全,servlet本身设计是单实例多线程的。既然是多线程肯定会涉及到线程安全!

如上实例变量count为实例变量,就不是安全的,多线程读写过程中就会出错。

那么问题转化为为什么实例变量在多线程中不安全?(不加锁)。如果把count放在方法中是否是线程安全呢?回答是是的。

关于如何设置servlet为线程安全有哪些方法,生命周期,以后专门会学习,在此不在叙述。

2.jvm的基本内存模型

基于jdk1.6的jvm内存模型。

java堆

存放实例信息:比如类的信息,实例变量信息。

存放数组。

多线程共享内存

java虚拟机栈

存放基本数据类型的变量,对象的引用

线程私有。

方法区

类实例的方法信息

常量池:静态常量

本地方法区

调用本地计算机其他函数,比如arraylist的实现中调用本地操作数组方法copyArray

寄存器,等。

简单的概述如上,那么例子中count应该存放在堆中,多线程数据共享区域,很明显当多个线程同时修改和读取的时候肯定就会达不到预期效果。

3.java类的加载过程

我们在来看一个类的加载过程和内存区域划分。

加载,链接(验证,准备,解析),初始化

加载:就是把字节码加载到jvm虚拟机中

验证:对字节码文件进行校验是否有错误,比如:操作文件是否是有了try

准备:对类信息等分配内存空间,比如堆,栈中划分内存(参考上面jvm模型)。对静态数据进行默认初始化 比如 int = 0;

解析:就是把符号引用转为直接引用

     看个例子: User user = new User();在未加载时候,user仅仅是一个字符(符号引用)它指向了一个实例。但是这个实例还不存在,准备过程之后,实例分配了内存那么就会有内存地址或者物理地址(直接引用)

初始化:对静态数据初始化。

比如 :static int = 1 ;在准备的时候赋值为0,初始化的时候才赋值为1;

调用构造器。


关于类加载,jvm模型理解,实在是很多很复杂,把复杂的消化并理解华为简单的过程也是学习。


上面是在下的肤浅认识,如有错误请指正。
切勿全相信楼主所说!

你可能感兴趣的:(JAVA认知)