面试官:为什么说ArrayList线程不安全?

阿里云国内75折 回扣 微信号:monov8
阿里云国际,腾讯云国际,低至75折。AWS 93折 免费开户实名账号 代冲值 优惠多多 微信号:monov8 飞机:@monov6

本博客知识点收录于⭐️《JavaSE系列教程》⭐️

1线程安全与不安全集合

我们学习集合的时候发现集合存在由线程安全集合和线程不安全集合线程安全效率低安全性高反之线程不安全效率高安全性低线程不安全的集合有VectorStackHashtable等

  • 查看Vector和Hashtable等源代码

在这里插入图片描述

线程安全集合中的方法大部分都加上了synchronized关键字来保证线程的同步

  • 线程不安全集合

在这里插入图片描述

2线程不安全集合测试

  • 数据覆盖问题
package com.dfbz.demo05;

import java.util.ArrayList;

/**
 * @author lscl
 * @version 1.0
 * @intro:
 */
public class Demo01_集合的线程安全问题 {
    public static void main(String[] args) throws InterruptedException {
        ArrayList<String> arr = new ArrayList<>();
        for (int j = 0; j < 20; ++j) {
            new Thread(() -> {
                for (int i = 0; i < 100; i++) {
                    arr.add("1");
                    try {
                        // 然线程安全问题更加突出
                        Thread.sleep(10);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }).start();
        }
    }
}

运行代码发现出现数组下标越界异常

在这里插入图片描述

分析ArrayList源码

  • 假设此时size为9size+1并没有大于数组的默认长度10并没有造成数组的扩容等待代码将集合的9下标赋值后size++还没来得及运算CPU的执行权就被其他的线程抢走了此时size仍旧为9但此时集合中已经存储了10个元素了等到其他线程来执行ensureCapacityInternal(9+1)—>ensureCapacityInternal—>ensureExplicitCapacity发现10-10还是小于0依旧不扩容代码执行elementData[size++]=e时还没执行线程执行权由回到了第一条线程size++变为10然后线程执行器又变回执行elementData[size++]=e这段代码时的那个线程出现了elementData[10]=e出现数组下标越界

在这里插入图片描述

TipsHashMap同样会出现这个问题将集合换成Vector或者Stack等线程安全集合可以解决这些问题或者使用JDK提供的其他线程同步集合也可以解决这些问题

阿里云国内75折 回扣 微信号:monov8
阿里云国际,腾讯云国际,低至75折。AWS 93折 免费开户实名账号 代冲值 优惠多多 微信号:monov8 飞机:@monov6