多线程与高并发面试题
一、请解释一下对象的创建过程
public class T { int m = 8; } T t = new T();
1、给m申请内存,将m进行半初始化,初始化0
2、调用构造方法,给m赋值8
3、将t对象的引用指向m
二、DCL与volatile问题
1、volatile:保证线程可见性,防止指令重排序
2、指令重排:
对象初始化的三个步骤:①申请内存,设默认值
②调用构造,设初始值
③建立关系
指令重排会将③放到②前
3、DCL要加volatile防止指令重排序
public class DclSingleton {
private static volatile DclSingleton singleton;
private DclSingleton() {
}
public static DclSingleton getDclSingleton() {
if (singleton == null) { 这行加判空是为了提高效率,线程抢锁是比较消耗性能的
synchronized (DclSingleton.class) {
if (singleton == null) { 这行判空是在第一个线程创建对象同时,可能第二个线程调用getDclSingleton,并且通过了第一个判空,在这里因为拿不到锁阻塞。当对象创建完成后,若此处没有判空,对象会被重复创建
singleton = new DclSingleton();
}
}
}
return singleton;
}
}
有两个线程,线程1抢到锁发现没有singleton对象后会new对象。
new对象时如果发生指令重排:先申请内存赋默认值-->对象和变量建立关联关系-->赋初始值-->此时线程2进来判断第一个singleton==null,假如对象中有一个成员变量,那么此时成员变量已经被赋初始值,线程2发现不为null,会直接返回singleton(半初始化对象)
三、对象在内存中的存储布局
markword(8字节)、类型指针(4字节)、实例数据、对齐(根据前三部分在内存中所占大小决定,需要被8整除)
这4部分的空间要能被8整除,如果不能被整除的要对齐
四、Object o = new Object()在内存中占多少字节
16字节
作者:http://cnblogs.com/lyc-code/
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文链接,否则保留追究法律责任的权力。