面试题

1.HashMap在多线程情况下,可能出现问题的环境有哪些?

HashMap是数组+单向链表/红黑树的结构,可能出现问题。
①在对一个数组位置上为空新增一个节点时,若多线程同时tab[i] = new Node(),则其他线程操作的数据将会丢失。

2.ConcurrentHashMap是如何解决上面的问题的?

①针对数据位置上为空,多线程同时新增的问题,采用CAS(乐观锁)的方式新增元素,若失败,则通过外部的死循环再次进行新增,此时就会追加在链表上。

 for (Node<K,V>[] tab = table;;) {
            Node<K,V> f; int n, i, fh;
            if (tab == null || (n = tab.length) == 0)
                tab = initTable();
            else if ((f = tabAt(tab, i = (n - 1) & hash)) == null) {
            //若CAS失败,则再次循环,就将走下面省略的部分代码
                if (casTabAt(tab, i, null,
                             new Node<K,V>(hash, key, value, null)))
                    break;                   // no lock when adding to empty bin
            }
            ....

3.ArrayList的线程不安全是在哪处代码上?

在新增操作中,会通过size++的方式获取数组下标,而这种方式本身就是线程不安全的,可能出现数据被清除或空元素的情况。

elementData[size++] = e;

4.CopyOnWriteArrayList是如何解决上面的问题的?

是使用ReentrantLock加锁的方式解决。

final ReentrantLock lock = this.lock;
        lock.lock();
        try {
            Object[] elements = getArray();
            int len = elements.length;
            //需要注意的是,每次新增都会创建一个新的数组,因此效率很低
            Object[] newElements = Arrays.copyOf(elements, len + 1);
            newElements[len] = e;
            setArray(newElements);
            return true;
        } finally {
            lock.unlock();
        }

5.JVM内存结构和java内存模型的区别

JVM内存结构也就是 堆、栈、元空间(方法区)、程序计数器等。

java内存模型(JMM)是指多线程的通信问题,涉及工作内存和主内存、共享变量和共享变量副本、volatile和synchronized。
volatile修饰的变量,在多线程操作情况下,线程可以及时获取变量的最新值,但是对于获取变量后再进行赋值操作,在多线程情况下依旧可能出现数据问题。这是因为volatile只能保证加载变量值从主内存获取,但是获取到之后的赋值是在工作内存中进行,并会写到主内存中的。因此当多个线程已经从主内存加载到值后,再进行操作不能保证数据安全。
依然还是需要通过synchronized加锁方式解决。

6.以下变量的等值比较结果

        Integer i1 = 1;
        Integer i2 = new Integer(1);
        Integer i3 = Integer.valueOf(1);
        System.out.println(i1 == i2);
        System.out.println(i1 == i3);
        System.out.println(i2 == i3);

结果是:

false
true
false

通过valueOf()或自动装箱方式定义的Byte/Short/Integer/Long对象,在-128~127之间时,会从缓存中获取,而通过new Integer(1)方式定义的则是新建的对象。
若这3个变量都是130,那么结果就将都是false,因为自动装箱也就是valueOf()对于超出范围的,直接新建对象。

        Integer i1 = 130;
        Integer i1_2 = 130;
        Integer i2 = new Integer(130);
        Integer i3 = Integer.valueOf(130);
        System.out.println(i1 == i1_2);
        System.out.println(i1 == i2);
        System.out.println(i1 == i3);
        System.out.println(i2 == i3);

结果:

false
false
false
false
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值