多线程与高并发面试题

一、请解释一下对象的创建过程

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字节

 

posted @ 2022-03-07 11:24  showMeTheCodes  阅读(288)  评论(0编辑  收藏  举报